Example #1
0
        public AesXtsFile(OpenMode mode, IFile baseFile, string path, ReadOnlySpan <byte> kekSeed, ReadOnlySpan <byte> verificationKey, int blockSize)
        {
            Mode            = mode;
            BaseFile        = baseFile;
            Path            = path;
            KekSeed         = kekSeed.ToArray();
            VerificationKey = verificationKey.ToArray();
            BlockSize       = blockSize;

            Header = new AesXtsFileHeader(BaseFile);

            if (!Header.TryDecryptHeader(Path, KekSeed, VerificationKey))
            {
                ThrowHelper.ThrowResult(ResultFs.AesXtsFileHeaderInvalidKeys, "NAX0 key derivation failed.");
            }

            if (HeaderLength + Util.AlignUp(Header.Size, 0x10) > baseFile.GetSize())
            {
                ThrowHelper.ThrowResult(ResultFs.AesXtsFileTooShort, "NAX0 key derivation failed.");
            }

            IStorage encStorage = BaseFile.AsStorage().Slice(HeaderLength, Util.AlignUp(Header.Size, 0x10));

            BaseStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Header.DecryptedKey1, Header.DecryptedKey2, BlockSize, true), 4, true);
        }
Example #2
0
        private void RenameDirectoryImpl(string srcDir, string dstDir, bool doRollback)
        {
            IDirectory dir = OpenDirectory(dstDir, OpenDirectoryMode.All);

            foreach (DirectoryEntry entry in dir.Read())
            {
                string subSrcPath = $"{srcDir}/{entry.Name}";
                string subDstPath = $"{dstDir}/{entry.Name}";

                if (entry.Type == DirectoryEntryType.Directory)
                {
                    RenameDirectoryImpl(subSrcPath, subDstPath, doRollback);
                }

                if (entry.Type == DirectoryEntryType.File)
                {
                    if (doRollback)
                    {
                        if (TryReadXtsHeader(subDstPath, subDstPath, out AesXtsFileHeader header))
                        {
                            WriteXtsHeader(header, subDstPath, subSrcPath);
                        }
                    }
                    else
                    {
                        AesXtsFileHeader header = ReadXtsHeader(subDstPath, subSrcPath);
                        WriteXtsHeader(header, subDstPath, subDstPath);
                    }
                }
            }
        }
Example #3
0
        private void WriteXtsHeader(AesXtsFileHeader header, string filePath, string keyPath)
        {
            Debug.Assert(PathTools.IsNormalized(filePath.AsSpan()));
            Debug.Assert(PathTools.IsNormalized(keyPath.AsSpan()));

            header.EncryptHeader(keyPath, KekSource, ValidationKey);

            using (IFile file = BaseFileSystem.OpenFile(filePath, OpenMode.ReadWrite))
            {
                file.Write(header.ToBytes(false), 0, WriteOption.Flush);
            }
        }
Example #4
0
        private bool TryReadXtsHeader(string filePath, string keyPath, out AesXtsFileHeader header)
        {
            Debug.Assert(PathTools.IsNormalized(filePath.AsSpan()));
            Debug.Assert(PathTools.IsNormalized(keyPath.AsSpan()));

            using (IFile file = BaseFileSystem.OpenFile(filePath, OpenMode.Read))
            {
                header = new AesXtsFileHeader(file);

                return(header.TryDecryptHeader(keyPath, KekSource, ValidationKey));
            }
        }
Example #5
0
        /// <summary>
        /// Creates a new <see cref="AesXtsFile"/> using the provided key.
        /// </summary>
        /// <param name="path">The full path of the file to create.</param>
        /// <param name="size">The initial size of the created file.</param>
        /// <param name="options">Flags to control how the file is created.
        /// Should usually be <see cref="CreateFileOptions.None"/></param>
        /// <param name="key">The 256-bit key containing a 128-bit data key followed by a 128-bit tweak key.</param>
        public void CreateFile(string path, long size, CreateFileOptions options, byte[] key)
        {
            long containerSize = AesXtsFile.HeaderLength + Util.AlignUp(size, 0x10);

            BaseFileSystem.CreateFile(path, containerSize, options);

            var header = new AesXtsFileHeader(key, size, path, KekSource, ValidationKey);

            using (IFile baseFile = BaseFileSystem.OpenFile(path, OpenMode.Write))
            {
                baseFile.Write(header.ToBytes(false), 0);
            }
        }
Example #6
0
        public AesXtsFile(OpenMode mode, IFile baseFile, string path, ReadOnlySpan <byte> kekSeed, ReadOnlySpan <byte> verificationKey, int blockSize)
        {
            Mode            = mode;
            BaseFile        = baseFile;
            Path            = path;
            KekSeed         = kekSeed.ToArray();
            VerificationKey = verificationKey.ToArray();
            BlockSize       = blockSize;

            Header = new AesXtsFileHeader(BaseFile);

            if (!Header.TryDecryptHeader(Path, KekSeed, VerificationKey))
            {
                throw new ArgumentException("NAX0 key derivation failed.");
            }

            IStorage encStorage = BaseFile.AsStorage().Slice(HeaderLength, Util.AlignUp(Header.Size, 0x10));

            BaseStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Header.DecryptedKey1, Header.DecryptedKey2, BlockSize, true), 4, true);
        }
Example #7
0
        public void RenameFile(string srcPath, string dstPath)
        {
            srcPath = PathTools.Normalize(srcPath);
            dstPath = PathTools.Normalize(dstPath);

            AesXtsFileHeader header = ReadXtsHeader(srcPath, srcPath);

            BaseFileSystem.RenameFile(srcPath, dstPath);

            try
            {
                WriteXtsHeader(header, dstPath, dstPath);
            }
            catch (Exception)
            {
                BaseFileSystem.RenameFile(dstPath, srcPath);
                WriteXtsHeader(header, srcPath, srcPath);

                throw;
            }
        }