コード例 #1
0
ファイル: Volumes.c プロジェクト: Clockwork-Sphinx/VeraCrypt
// Creates a volume header in memory
int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, char *header, int ea, int mode, Password *password,
                                int pkcs5_prf, int pim, char *masterKeydata, PCRYPTO_INFO *retInfo,
                                unsigned __int64 volumeSize, unsigned __int64 hiddenVolumeSize,
                                unsigned __int64 encryptedAreaStart, unsigned __int64 encryptedAreaLength, uint16 requiredProgramVersion, uint32 headerFlags, uint32 sectorSize, BOOL bWipeMode)
{
    unsigned char *p = (unsigned char *) header;
    static CRYPTOPP_ALIGN_DATA(16) KEY_INFO keyInfo;

    int nUserKeyLen = password->Length;
    PCRYPTO_INFO cryptoInfo = crypto_open ();
    static char dk[MASTER_KEYDATA_SIZE];
    int x;
    int retVal = 0;
    int primaryKeyOffset;

    if (cryptoInfo == NULL)
        return ERR_OUTOFMEMORY;

    // if no PIM specified, use default value
    if (pim < 0)
        pim = 0;

    memset (header, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE);

    VirtualLock (&keyInfo, sizeof (keyInfo));
    VirtualLock (&dk, sizeof (dk));

    /* Encryption setup */

    if (masterKeydata == NULL)
    {
        // We have no master key data (creating a new volume) so we'll use the TrueCrypt RNG to generate them

        int bytesNeeded;

        switch (mode)
        {

        default:
            bytesNeeded = EAGetKeySize (ea) * 2;	// Size of primary + secondary key(s)
        }

        if (!RandgetBytes (hwndDlg, keyInfo.master_keydata, bytesNeeded, TRUE))
            return ERR_CIPHER_INIT_WEAK_KEY;
    }
    else
    {
        // We already have existing master key data (the header is being re-encrypted)
        memcpy (keyInfo.master_keydata, masterKeydata, MASTER_KEYDATA_SIZE);
    }

    // User key
    memcpy (keyInfo.userKey, password->Text, nUserKeyLen);
    keyInfo.keyLength = nUserKeyLen;
    keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, pim, FALSE, bBoot);

    // User selected encryption algorithm
    cryptoInfo->ea = ea;

    // User selected PRF
    cryptoInfo->pkcs5 = pkcs5_prf;
    cryptoInfo->bTrueCryptMode = FALSE;
    cryptoInfo->noIterations = keyInfo.noIterations;
    cryptoInfo->volumePim = pim;

    // Mode of operation
    cryptoInfo->mode = mode;

    // Salt for header key derivation
    if (!RandgetBytes (hwndDlg, keyInfo.salt, PKCS5_SALT_SIZE, !bWipeMode))
        return ERR_CIPHER_INIT_WEAK_KEY;

    // PBKDF2 (PKCS5) is used to derive primary header key(s) and secondary header key(s) (XTS) from the password/keyfiles
    switch (pkcs5_prf)
    {
    case SHA512:
        derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                           PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
        break;

    case SHA256:
        derive_key_sha256 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                           PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
        break;

    case RIPEMD160:
        derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                              PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
        break;

    case WHIRLPOOL:
        derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                              PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
        break;

    default:
        // Unknown/wrong ID
        TC_THROW_FATAL_EXCEPTION;
    }

    /* Header setup */

    // Salt
    mputBytes (p, keyInfo.salt, PKCS5_SALT_SIZE);

    // Magic
    mputLong (p, 0x56455241);

    // Header version
    mputWord (p, VOLUME_HEADER_VERSION);
    cryptoInfo->HeaderVersion = VOLUME_HEADER_VERSION;

    // Required program version to handle this volume
    mputWord (p, requiredProgramVersion != 0 ? requiredProgramVersion : TC_VOLUME_MIN_REQUIRED_PROGRAM_VERSION);

    // CRC of the master key data
    x = GetCrc32(keyInfo.master_keydata, MASTER_KEYDATA_SIZE);
    mputLong (p, x);

    // Reserved fields
    p += 2 * 8;

    // Size of hidden volume (if any)
    cryptoInfo->hiddenVolumeSize = hiddenVolumeSize;
    mputInt64 (p, cryptoInfo->hiddenVolumeSize);

    cryptoInfo->hiddenVolume = cryptoInfo->hiddenVolumeSize != 0;

    // Volume size
    cryptoInfo->VolumeSize.Value = volumeSize;
    mputInt64 (p, volumeSize);

    // Encrypted area start
    cryptoInfo->EncryptedAreaStart.Value = encryptedAreaStart;
    mputInt64 (p, encryptedAreaStart);

    // Encrypted area size
    cryptoInfo->EncryptedAreaLength.Value = encryptedAreaLength;
    mputInt64 (p, encryptedAreaLength);

    // Flags
    cryptoInfo->HeaderFlags = headerFlags;
    mputLong (p, headerFlags);

    // Sector size
    if (sectorSize < TC_MIN_VOLUME_SECTOR_SIZE
            || sectorSize > TC_MAX_VOLUME_SECTOR_SIZE
            || sectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
    {
        TC_THROW_FATAL_EXCEPTION;
    }

    cryptoInfo->SectorSize = sectorSize;
    mputLong (p, sectorSize);

    // CRC of the header fields
    x = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
    p = header + TC_HEADER_OFFSET_HEADER_CRC;
    mputLong (p, x);

    // The master key data
    memcpy (header + HEADER_MASTER_KEYDATA_OFFSET, keyInfo.master_keydata, MASTER_KEYDATA_SIZE);


    /* Header encryption */

    switch (mode)
    {

    default:
        // The secondary key (if cascade, multiple concatenated)
        memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea));
        primaryKeyOffset = 0;
    }

    retVal = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks);
    if (retVal != ERR_SUCCESS)
        return retVal;

    // Mode of operation
    if (!EAInitMode (cryptoInfo))
        return ERR_OUTOFMEMORY;


    // Encrypt the entire header (except the salt)
    EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET,
                   HEADER_ENCRYPTED_DATA_SIZE,
                   cryptoInfo);


    /* cryptoInfo setup for further use (disk format) */

    // Init with the master key(s)
    retVal = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks);
    if (retVal != ERR_SUCCESS)
        return retVal;

    memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE);

    switch (cryptoInfo->mode)
    {

    default:
        // The secondary master key (if cascade, multiple concatenated)
        memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea));
    }

    // Mode of operation
    if (!EAInitMode (cryptoInfo))
        return ERR_OUTOFMEMORY;


#ifdef VOLFORMAT
    if (!bInPlaceEncNonSys && (showKeys || (bBoot && !masterKeydata)))
    {
        BOOL dots3 = FALSE;
        int i, j;

        j = EAGetKeySize (ea);

        if (j > NBR_KEY_BYTES_TO_DISPLAY)
        {
            dots3 = TRUE;
            j = NBR_KEY_BYTES_TO_DISPLAY;
        }

        MasterKeyGUIView[0] = 0;
        for (i = 0; i < j; i++)
        {
            wchar_t tmp2[8] = {0};
            StringCchPrintfW (tmp2, ARRAYSIZE(tmp2), L"%02X", (int) (unsigned char) keyInfo.master_keydata[i + primaryKeyOffset]);
            StringCchCatW (MasterKeyGUIView, ARRAYSIZE(MasterKeyGUIView), tmp2);
        }

        HeaderKeyGUIView[0] = 0;
        for (i = 0; i < NBR_KEY_BYTES_TO_DISPLAY; i++)
        {
            wchar_t tmp2[8];
            StringCchPrintfW (tmp2, ARRAYSIZE(tmp2), L"%02X", (int) (unsigned char) dk[primaryKeyOffset + i]);
            StringCchCatW (HeaderKeyGUIView, ARRAYSIZE(HeaderKeyGUIView), tmp2);
        }

        if (dots3)
        {
            DisplayPortionsOfKeys (hHeaderKey, hMasterKey, HeaderKeyGUIView, MasterKeyGUIView, !showKeys);
        }
        else
        {
            SendMessage (hMasterKey, WM_SETTEXT, 0, (LPARAM) MasterKeyGUIView);
            SendMessage (hHeaderKey, WM_SETTEXT, 0, (LPARAM) HeaderKeyGUIView);
        }
    }
#endif	// #ifdef VOLFORMAT

    burn (dk, sizeof(dk));
    burn (&keyInfo, sizeof (keyInfo));

    *retInfo = cryptoInfo;
    return 0;
}
コード例 #2
0
ファイル: Volumes.c プロジェクト: Clockwork-Sphinx/VeraCrypt
int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, int selected_pkcs5_prf, int pim, BOOL truecryptMode, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo)
{
    char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
    CRYPTOPP_ALIGN_DATA(16) KEY_INFO keyInfo;
    PCRYPTO_INFO cryptoInfo;
    char dk[MASTER_KEYDATA_SIZE];
    int enqPkcs5Prf, pkcs5_prf;
    uint16 headerVersion;
    int status = ERR_PARAMETER_INCORRECT;
    int primaryKeyOffset;

    TC_EVENT keyDerivationCompletedEvent;
    TC_EVENT noOutstandingWorkItemEvent;
    KeyDerivationWorkItem *keyDerivationWorkItems;
    KeyDerivationWorkItem *item;
    int pkcs5PrfCount = LAST_PRF_ID - FIRST_PRF_ID + 1;
    size_t encryptionThreadCount = GetEncryptionThreadCount();
    size_t queuedWorkItems = 0;
    LONG outstandingWorkItemCount = 0;
    int i;

    // if no PIM specified, use default value
    if (pim < 0)
        pim = 0;

    if (truecryptMode)
    {
        // SHA-256 not supported in TrueCrypt mode
        if (selected_pkcs5_prf == SHA256)
            return ERR_PARAMETER_INCORRECT;
        pkcs5PrfCount--; // don't count SHA-256 in case of TrueCrypt mode
    }

    if (retHeaderCryptoInfo != NULL)
    {
        cryptoInfo = retHeaderCryptoInfo;
    }
    else
    {
        if (!retInfo)
            return ERR_PARAMETER_INCORRECT;

        cryptoInfo = *retInfo = crypto_open ();
        if (cryptoInfo == NULL)
            return ERR_OUTOFMEMORY;
    }

    /* use thread pool only if no PRF was specified */
    if ((selected_pkcs5_prf == 0) && (encryptionThreadCount > 1))
    {
        keyDerivationWorkItems = TCalloc (sizeof (KeyDerivationWorkItem) * pkcs5PrfCount);
        if (!keyDerivationWorkItems)
            return ERR_OUTOFMEMORY;

        for (i = 0; i < pkcs5PrfCount; ++i)
            keyDerivationWorkItems[i].Free = TRUE;

#ifdef DEVICE_DRIVER
        KeInitializeEvent (&keyDerivationCompletedEvent, SynchronizationEvent, FALSE);
        KeInitializeEvent (&noOutstandingWorkItemEvent, SynchronizationEvent, TRUE);
#else
        keyDerivationCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
        if (!keyDerivationCompletedEvent)
        {
            TCfree (keyDerivationWorkItems);
            return ERR_OUTOFMEMORY;
        }

        noOutstandingWorkItemEvent = CreateEvent (NULL, FALSE, TRUE, NULL);
        if (!noOutstandingWorkItemEvent)
        {
            CloseHandle (keyDerivationCompletedEvent);
            TCfree (keyDerivationWorkItems);
            return ERR_OUTOFMEMORY;
        }
#endif
    }

#ifndef DEVICE_DRIVER
    VirtualLock (&keyInfo, sizeof (keyInfo));
    VirtualLock (&dk, sizeof (dk));
#endif

    crypto_loadkey (&keyInfo, password->Text, (int) password->Length);

    // PKCS5 is used to derive the primary header key(s) and secondary header key(s) (XTS mode) from the password
    memcpy (keyInfo.salt, encryptedHeader + HEADER_SALT_OFFSET, PKCS5_SALT_SIZE);

    // Test all available PKCS5 PRFs
    for (enqPkcs5Prf = FIRST_PRF_ID; enqPkcs5Prf <= LAST_PRF_ID || queuedWorkItems > 0; ++enqPkcs5Prf)
    {
        // if a PRF is specified, we skip all other PRFs
        if (selected_pkcs5_prf != 0 && enqPkcs5Prf != selected_pkcs5_prf)
            continue;

        // skip SHA-256 in case of TrueCrypt mode
        if (truecryptMode && (enqPkcs5Prf == SHA256))
            continue;

        if ((selected_pkcs5_prf == 0) && (encryptionThreadCount > 1))
        {
            // Enqueue key derivation on thread pool
            if (queuedWorkItems < encryptionThreadCount && enqPkcs5Prf <= LAST_PRF_ID)
            {
                for (i = 0; i < pkcs5PrfCount; ++i)
                {
                    item = &keyDerivationWorkItems[i];
                    if (item->Free)
                    {
                        item->Free = FALSE;
                        item->KeyReady = FALSE;
                        item->Pkcs5Prf = enqPkcs5Prf;

                        EncryptionThreadPoolBeginKeyDerivation (&keyDerivationCompletedEvent, &noOutstandingWorkItemEvent,
                                                                &item->KeyReady, &outstandingWorkItemCount, enqPkcs5Prf, keyInfo.userKey,
                                                                keyInfo.keyLength, keyInfo.salt, get_pkcs5_iteration_count (enqPkcs5Prf, pim, truecryptMode, bBoot), item->DerivedKey);

                        ++queuedWorkItems;
                        break;
                    }
                }

                if (enqPkcs5Prf < LAST_PRF_ID)
                    continue;
            }
            else
                --enqPkcs5Prf;

            // Wait for completion of a key derivation
            while (queuedWorkItems > 0)
            {
                for (i = 0; i < pkcs5PrfCount; ++i)
                {
                    item = &keyDerivationWorkItems[i];
                    if (!item->Free && InterlockedExchangeAdd (&item->KeyReady, 0) == TRUE)
                    {
                        pkcs5_prf = item->Pkcs5Prf;
                        keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, pim, truecryptMode, bBoot);
                        memcpy (dk, item->DerivedKey, sizeof (dk));

                        item->Free = TRUE;
                        --queuedWorkItems;
                        goto KeyReady;
                    }
                }

                if (queuedWorkItems > 0)
                    TC_WAIT_EVENT (keyDerivationCompletedEvent);
            }
            continue;
KeyReady:
            ;
        }
        else
        {
            pkcs5_prf = enqPkcs5Prf;
            keyInfo.noIterations = get_pkcs5_iteration_count (enqPkcs5Prf, pim, truecryptMode, bBoot);

            switch (pkcs5_prf)
            {
            case RIPEMD160:
                derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                                      PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
                break;

            case SHA512:
                derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                                   PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
                break;

            case WHIRLPOOL:
                derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                                      PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
                break;

            case SHA256:
                derive_key_sha256 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
                                   PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
                break;

            default:
                // Unknown/wrong ID
                TC_THROW_FATAL_EXCEPTION;
            }
        }

        // Test all available modes of operation
        for (cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID;
                cryptoInfo->mode <= LAST_MODE_OF_OPERATION;
                cryptoInfo->mode++)
        {
            switch (cryptoInfo->mode)
            {

            default:
                primaryKeyOffset = 0;
            }

            // Test all available encryption algorithms
            for (cryptoInfo->ea = EAGetFirst ();
                    cryptoInfo->ea != 0;
                    cryptoInfo->ea = EAGetNext (cryptoInfo->ea))
            {
                int blockSize;

                if (!EAIsModeSupported (cryptoInfo->ea, cryptoInfo->mode))
                    continue;	// This encryption algorithm has never been available with this mode of operation

                blockSize = CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea));

                status = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks);
                if (status == ERR_CIPHER_INIT_FAILURE)
                    goto err;

                // Init objects related to the mode of operation

                if (cryptoInfo->mode == XTS)
                {
                    // Copy the secondary key (if cascade, multiple concatenated)
                    memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea));

                    // Secondary key schedule
                    if (!EAInitMode (cryptoInfo))
                    {
                        status = ERR_MODE_INIT_FAILED;
                        goto err;
                    }
                }
                else
                {
                    continue;
                }

                // Copy the header for decryption
                memcpy (header, encryptedHeader, sizeof (header));

                // Try to decrypt header

                DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);

                // Magic 'VERA' or 'TRUE' depending if we are in TrueCrypt mode or not
                if ((truecryptMode && GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545)
                        || (!truecryptMode && GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x56455241)
                   )
                    continue;

                // Header version
                headerVersion = GetHeaderField16 (header, TC_HEADER_OFFSET_VERSION);

                if (headerVersion > VOLUME_HEADER_VERSION)
                {
                    status = ERR_NEW_VERSION_REQUIRED;
                    goto err;
                }

                // Check CRC of the header fields
                if (!ReadVolumeHeaderRecoveryMode
                        && headerVersion >= 4
                        && GetHeaderField32 (header, TC_HEADER_OFFSET_HEADER_CRC) != GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC))
                    continue;

                // Required program version
                cryptoInfo->RequiredProgramVersion = GetHeaderField16 (header, TC_HEADER_OFFSET_REQUIRED_VERSION);
                if (truecryptMode)
                {
                    if (cryptoInfo->RequiredProgramVersion < 0x600 || cryptoInfo->RequiredProgramVersion > 0x71a)
                    {
                        status = ERR_UNSUPPORTED_TRUECRYPT_FORMAT | (((int)cryptoInfo->RequiredProgramVersion) << 16);
                        goto err;
                    }
                    cryptoInfo->LegacyVolume = FALSE;
                }
                else
                    cryptoInfo->LegacyVolume = cryptoInfo->RequiredProgramVersion < 0x10b;

                // Check CRC of the key set
                if (!ReadVolumeHeaderRecoveryMode
                        && GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE))
                    continue;

                // Now we have the correct password, cipher, hash algorithm, and volume type

                // Check the version required to handle this volume
                if (!truecryptMode && (cryptoInfo->RequiredProgramVersion > VERSION_NUM))
                {
                    status = ERR_NEW_VERSION_REQUIRED;
                    goto err;
                }

                // Header version
                cryptoInfo->HeaderVersion = headerVersion;

                // Volume creation time (legacy)
                cryptoInfo->volume_creation_time = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_CREATION_TIME).Value;

                // Header creation time (legacy)
                cryptoInfo->header_creation_time = GetHeaderField64 (header, TC_HEADER_OFFSET_MODIFICATION_TIME).Value;

                // Hidden volume size (if any)
                cryptoInfo->hiddenVolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE).Value;

                // Hidden volume status
                cryptoInfo->hiddenVolume = (cryptoInfo->hiddenVolumeSize != 0);

                // Volume size
                cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE);

                // Encrypted area size and length
                cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START);
                cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH);

                // Flags
                cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS);

                // Sector size
                if (headerVersion >= 5)
                    cryptoInfo->SectorSize = GetHeaderField32 (header, TC_HEADER_OFFSET_SECTOR_SIZE);
                else
                    cryptoInfo->SectorSize = TC_SECTOR_SIZE_LEGACY;

                if (cryptoInfo->SectorSize < TC_MIN_VOLUME_SECTOR_SIZE
                        || cryptoInfo->SectorSize > TC_MAX_VOLUME_SECTOR_SIZE
                        || cryptoInfo->SectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
                {
                    status = ERR_PARAMETER_INCORRECT;
                    goto err;
                }

                // Preserve scheduled header keys if requested
                if (retHeaderCryptoInfo)
                {
                    if (retInfo == NULL)
                    {
                        cryptoInfo->pkcs5 = pkcs5_prf;
                        cryptoInfo->noIterations = keyInfo.noIterations;
                        cryptoInfo->bTrueCryptMode = truecryptMode;
                        cryptoInfo->volumePim = pim;
                        goto ret;
                    }

                    cryptoInfo = *retInfo = crypto_open ();
                    if (cryptoInfo == NULL)
                    {
                        status = ERR_OUTOFMEMORY;
                        goto err;
                    }

                    memcpy (cryptoInfo, retHeaderCryptoInfo, sizeof (*cryptoInfo));
                }

                // Master key data
                memcpy (keyInfo.master_keydata, header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE);
                memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE);

                // PKCS #5
                memcpy (cryptoInfo->salt, keyInfo.salt, PKCS5_SALT_SIZE);
                cryptoInfo->pkcs5 = pkcs5_prf;
                cryptoInfo->noIterations = keyInfo.noIterations;
                cryptoInfo->bTrueCryptMode = truecryptMode;
                cryptoInfo->volumePim = pim;

                // Init the cipher with the decrypted master key
                status = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks);
                if (status == ERR_CIPHER_INIT_FAILURE)
                    goto err;

                switch (cryptoInfo->mode)
                {

                default:
                    // The secondary master key (if cascade, multiple concatenated)
                    memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea));

                }

                if (!EAInitMode (cryptoInfo))
                {
                    status = ERR_MODE_INIT_FAILED;
                    goto err;
                }

                status = ERR_SUCCESS;
                goto ret;
            }
        }
    }
    status = ERR_PASSWORD_WRONG;

err:
    if (cryptoInfo != retHeaderCryptoInfo)
    {
        crypto_close(cryptoInfo);
        *retInfo = NULL;
    }

ret:
    burn (&keyInfo, sizeof (keyInfo));
    burn (dk, sizeof(dk));

#ifndef DEVICE_DRIVER
    VirtualUnlock (&keyInfo, sizeof (keyInfo));
    VirtualUnlock (&dk, sizeof (dk));
#endif

    if ((selected_pkcs5_prf == 0) && (encryptionThreadCount > 1))
    {
        TC_WAIT_EVENT (noOutstandingWorkItemEvent);

        burn (keyDerivationWorkItems, sizeof (KeyDerivationWorkItem) * pkcs5PrfCount);
        TCfree (keyDerivationWorkItems);

#ifndef DEVICE_DRIVER
        CloseHandle (keyDerivationCompletedEvent);
        CloseHandle (noOutstandingWorkItemEvent);
#endif
    }

    return status;
}
コード例 #3
0
ファイル: Volumes.c プロジェクト: Clockwork-Sphinx/VeraCrypt
int ReadVolumeHeader (BOOL bBoot, char *header, Password *password, int pim, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo)
{
#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
    char dk[32 * 2];			// 2 * 256-bit key
#else
    char dk[32 * 2 * 3];		// 6 * 256-bit key
#endif

    PCRYPTO_INFO cryptoInfo;
    int status = ERR_SUCCESS;
    uint32 iterations = pim;
    iterations <<= 16;
    iterations |= bBoot;

    if (retHeaderCryptoInfo != NULL)
        cryptoInfo = retHeaderCryptoInfo;
    else
        cryptoInfo = *retInfo = crypto_open ();

    // PKCS5 PRF
#ifdef TC_WINDOWS_BOOT_SHA2
    derive_key_sha256 (password->Text, (int) password->Length, header + HEADER_SALT_OFFSET,
                       PKCS5_SALT_SIZE, iterations, dk, sizeof (dk));
#else
    derive_key_ripemd160 (password->Text, (int) password->Length, header + HEADER_SALT_OFFSET,
                          PKCS5_SALT_SIZE, iterations, dk, sizeof (dk));
#endif

    // Mode of operation
    cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID;

#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
    cryptoInfo->ea = 1;
#else
    // Test all available encryption algorithms
    for (cryptoInfo->ea = EAGetFirst (); cryptoInfo->ea != 0; cryptoInfo->ea = EAGetNext (cryptoInfo->ea))
#endif
    {
#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
#if defined (TC_WINDOWS_BOOT_SERPENT)
        serpent_set_key (dk, cryptoInfo->ks);
#elif defined (TC_WINDOWS_BOOT_TWOFISH)
        twofish_set_key ((TwofishInstance *) cryptoInfo->ks, (const u4byte *) dk);
#elif defined (TC_WINDOWS_BOOT_CAMELLIA)
        camellia_set_key (dk, cryptoInfo->ks);
#else
        status = EAInit (dk, cryptoInfo->ks);
        if (status == ERR_CIPHER_INIT_FAILURE)
            goto err;
#endif
#else
        status = EAInit (cryptoInfo->ea, dk, cryptoInfo->ks);
        if (status == ERR_CIPHER_INIT_FAILURE)
            goto err;
#endif
        // Secondary key schedule
#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
#if defined (TC_WINDOWS_BOOT_SERPENT)
        serpent_set_key (dk + 32, cryptoInfo->ks2);
#elif defined (TC_WINDOWS_BOOT_TWOFISH)
        twofish_set_key ((TwofishInstance *)cryptoInfo->ks2, (const u4byte *) (dk + 32));
#elif defined (TC_WINDOWS_BOOT_CAMELLIA)
        camellia_set_key (dk + 32, cryptoInfo->ks2);
#else
        EAInit (dk + 32, cryptoInfo->ks2);
#endif
#else
        EAInit (cryptoInfo->ea, dk + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2);
#endif

        // Try to decrypt header
        DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);

        // Check magic 'VERA' and CRC-32 of header fields and master keydata
        if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x56455241
                || (GetHeaderField16 (header, TC_HEADER_OFFSET_VERSION) >= 4 && GetHeaderField32 (header, TC_HEADER_OFFSET_HEADER_CRC) != GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC))
                || GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE))
        {
            EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
            status = ERR_PASSWORD_WRONG;
            goto err;
#else
            continue;
#endif
        }

        // Header decrypted
        status = 0;

        // Hidden volume status
        cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_HIDDEN_VOLUME_SIZE);
        cryptoInfo->hiddenVolume = (cryptoInfo->VolumeSize.LowPart != 0 || cryptoInfo->VolumeSize.HighPart != 0);

        // Volume size
        cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE);

        // Encrypted area size and length
        cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START);
        cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH);

        // Flags
        cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS);

#ifdef TC_WINDOWS_BOOT_SHA2
        cryptoInfo->pkcs5 = SHA256;
#else
        cryptoInfo->pkcs5 = RIPEMD160;
#endif

        memcpy (dk, header + HEADER_MASTER_KEYDATA_OFFSET, sizeof (dk));
        EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);

        if (retHeaderCryptoInfo)
            goto ret;

        // Init the encryption algorithm with the decrypted master key
#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
#if defined (TC_WINDOWS_BOOT_SERPENT)
        serpent_set_key (dk, cryptoInfo->ks);
#elif defined (TC_WINDOWS_BOOT_TWOFISH)
        twofish_set_key ((TwofishInstance *) cryptoInfo->ks, (const u4byte *) dk);
#elif defined (TC_WINDOWS_BOOT_CAMELLIA)
        camellia_set_key (dk, cryptoInfo->ks);
#else
        status = EAInit (dk, cryptoInfo->ks);
        if (status == ERR_CIPHER_INIT_FAILURE)
            goto err;
#endif
#else
        status = EAInit (cryptoInfo->ea, dk, cryptoInfo->ks);
        if (status == ERR_CIPHER_INIT_FAILURE)
            goto err;
#endif

        // The secondary master key (if cascade, multiple concatenated)
#ifdef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
#if defined (TC_WINDOWS_BOOT_SERPENT)
        serpent_set_key (dk + 32, cryptoInfo->ks2);
#elif defined (TC_WINDOWS_BOOT_TWOFISH)
        twofish_set_key ((TwofishInstance *)cryptoInfo->ks2, (const u4byte *) (dk + 32));
#elif defined (TC_WINDOWS_BOOT_CAMELLIA)
        camellia_set_key (dk + 32, cryptoInfo->ks2);
#else
        EAInit (dk + 32, cryptoInfo->ks2);
#endif
#else
        EAInit (cryptoInfo->ea, dk + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2);
#endif
        goto ret;
    }

    status = ERR_PASSWORD_WRONG;

err:
    if (cryptoInfo != retHeaderCryptoInfo)
    {
        crypto_close(cryptoInfo);
        *retInfo = NULL;
    }

ret:
    burn (dk, sizeof(dk));
    return status;
}
コード例 #4
0
static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
{
	EncryptionThreadPoolWorkItem *workItem;

	while (!StopPending)
	{
		TC_ACQUIRE_MUTEX (&DequeueMutex);

		workItem = &WorkItemQueue[DequeuePosition++];

		if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE)
			DequeuePosition = 0;

		while (!StopPending && GetWorkItemState (workItem) != WorkItemReady)
		{
			TC_WAIT_EVENT (WorkItemReadyEvent);
		}

		SetWorkItemState (workItem, WorkItemBusy);

		TC_RELEASE_MUTEX (&DequeueMutex);

		if (StopPending)
			break;

		switch (workItem->Type)
		{
		case DecryptDataUnitsWork:
			DecryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
			break;

		case EncryptDataUnitsWork:
			EncryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo);
			break;

		case DeriveKeyWork:
			switch (workItem->KeyDerivation.Pkcs5Prf)
			{
			case RIPEMD160:
				derive_key_ripemd160 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
					workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
				break;

			case SHA512:
				derive_key_sha512 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
					workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
				break;

			case WHIRLPOOL:
				derive_key_whirlpool (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
					workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
				break;

			case SHA256:
				derive_key_sha256 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
					workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
				break;

			case STREEBOG:
				derive_key_streebog(workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
					workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
				break;

			default:
				TC_THROW_FATAL_EXCEPTION;
			}

			InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE);
			TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent);

			if (InterlockedDecrement (workItem->KeyDerivation.OutstandingWorkItemCount) == 0)
				TC_SET_EVENT (*workItem->KeyDerivation.NoOutstandingWorkItemEvent);

			SetWorkItemState (workItem, WorkItemFree);
			TC_SET_EVENT (WorkItemCompletedEvent);
			continue;

		default:
			TC_THROW_FATAL_EXCEPTION;
		}

		if (workItem != workItem->FirstFragment)
		{
			SetWorkItemState (workItem, WorkItemFree);
			TC_SET_EVENT (WorkItemCompletedEvent);
		}

		if (InterlockedDecrement (&workItem->FirstFragment->OutstandingFragmentCount) == 0)
			TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent);
	}

#ifdef DEVICE_DRIVER
	PsTerminateSystemThread (STATUS_SUCCESS);
#else
	_endthreadex (0);
    return 0;
#endif
}