예제 #1
0
        public static TrueCryptResizeStatus ExtendVolumeAndFileSystem(Disk disk, byte[] password, long additionalNumberOfSectors)
        {
            Volume          partition = VolumeSelectionHelper.GetLastPartition(disk);
            TrueCryptVolume volume;

            try
            {
                volume = new TrueCryptVolume(partition, password);
            }
            catch (InvalidDataException)
            {
                return(TrueCryptResizeStatus.InvalidDisk);
            }
            catch (NotSupportedException)
            {
                return(TrueCryptResizeStatus.UnsupportedFormatVersion);
            }

            if (volume.IsHiddenVolume)
            {
                return(TrueCryptResizeStatus.HiddenVolume);
            }

            NTFSVolume ntfsVolume;

            try
            {
                ntfsVolume = new NTFSVolume(volume);
            }
            catch (InvalidDataException)
            {
                return(TrueCryptResizeStatus.UnsupportedFileSystem);
            }
            catch (NotSupportedException)
            {
                return(TrueCryptResizeStatus.UnsupportedFileSystem);
            }

            TrueCryptResizeStatus status = ExtendVolume(disk, password, additionalNumberOfSectors);

            if (status == TrueCryptResizeStatus.Success)
            {
                // Reinitialize the partition / volume
                partition  = VolumeSelectionHelper.GetLastPartition(disk);
                volume     = new TrueCryptVolume(partition, password);
                ntfsVolume = new NTFSVolume(volume);
                long availableBytes   = ntfsVolume.GetMaximumSizeToExtend();
                long availableSectors = availableBytes / disk.BytesPerSector;
                ntfsVolume.Extend(availableSectors);

                return(TrueCryptResizeStatus.Success);
            }
            else
            {
                return(status);
            }
        }
예제 #2
0
        /// <summary>
        /// Extend the partition and TrueCrypt volume
        /// </summary>
        public static TrueCryptResizeStatus ExtendVolume(Disk disk, byte[] password, long additionalNumberOfSectors)
        {
            Partition       partition = VolumeSelectionHelper.GetLastPartition(disk);
            TrueCryptVolume volume;

            try
            {
                volume = new TrueCryptVolume(partition, password);
            }
            catch (InvalidDataException)
            {
                return(TrueCryptResizeStatus.InvalidDisk);
            }
            catch (NotSupportedException)
            {
                return(TrueCryptResizeStatus.UnsupportedFormatVersion);
            }

            if (volume.IsHiddenVolume)
            {
                return(TrueCryptResizeStatus.HiddenVolume);
            }

            long availableBytes;

            if (partition is MBRPartition || partition is GPTPartition)
            {
                availableBytes = ExtendHelper.GetMaximumSizeToExtendPartition(partition);
            }
            else // Removable volume
            {
                availableBytes = additionalNumberOfSectors * volume.BytesPerSector;
            }

            TrueCryptHeader header = volume.Header;
            long            oldBackupHeaderOffset = (long)(header.MasterKeyScopeOffset + header.MasterKeyEncryptedAreaSize);
            long            newBackupHeaderOffset = (long)(header.MasterKeyScopeOffset + header.MasterKeyEncryptedAreaSize + (ulong)availableBytes);

            header.MasterKeyEncryptedAreaSize += (ulong)availableBytes;
            header.VolumeSize += (ulong)availableBytes;
            byte[] headerBytes = header.GetBytes(password);
            // Read backup header group from old end of the partition
            byte[] backupHeaderGroupBytes = partition.ReadSectors(oldBackupHeaderOffset / disk.BytesPerSector, TrueCryptVolume.VolumeHeaderGroupLength / disk.BytesPerSector);
            // Updated the backup header (using the stored salt)
            header.Salt = ByteReader.ReadBytes(backupHeaderGroupBytes, 0, 64);
            byte[] backupHeaderBytes = header.GetBytes(password);
            Array.Copy(backupHeaderBytes, 0, backupHeaderGroupBytes, 0, backupHeaderBytes.Length);

            if (partition is MBRPartition || partition is GPTPartition)
            {
                long availableSectors = availableBytes / disk.BytesPerSector;
                ExtendHelper.ExtendPartition((Partition)partition, availableSectors);
                // Reinitialize the partition
                partition = VolumeSelectionHelper.GetLastPartition(disk);
            }

            // Write backup header to the new end of the partition
            partition.WriteSectors(newBackupHeaderOffset / disk.BytesPerSector, backupHeaderGroupBytes);

            // Destroy the old backup header (to prevent decryption of the volume after the password has changed)
            byte[] temp = new byte[TrueCryptVolume.VolumeHeaderGroupLength];
            new Random().NextBytes(temp);
            partition.WriteSectors(oldBackupHeaderOffset / disk.BytesPerSector, temp);

            // Write an updated header
            partition.WriteSectors(0, headerBytes);

            return(TrueCryptResizeStatus.Success);
        }