public IStorage OpenDecryptedWarmBootStorage() { if (!IsDecrypted) { return(null); } IStorage warmBootStorage = OpenWarmBootStorage(); // Only Mariko warmboot storage is encrypted if (!IsMariko) { return(warmBootStorage); } int size = GetSectionSize(Package1Section.WarmBoot); int encryptedSectionSize = size - MarikoWarmBootPlainTextSectionSize; var plainTextSection = new SubStorage(warmBootStorage, 0, MarikoWarmBootPlainTextSectionSize); var encryptedSubStorage = new SubStorage(warmBootStorage, MarikoWarmBootPlainTextSectionSize, encryptedSectionSize); var zeroIv = new Buffer16(); IStorage decryptedSection = new AesCbcStorage(encryptedSubStorage, KeySet.MarikoBek, zeroIv.Bytes, true); decryptedSection = new CachedStorage(decryptedSection, 0x200, 1, true); return(new ConcatenationStorage(new List <IStorage> { plainTextSection, decryptedSection }, true)); }
public void Encrypt(ReadOnlySpan <byte> input, Span <byte> output) { int length = Math.Min(input.Length, output.Length); int blockCount = length >> 4; int leftover = length & 0xF; // Data units must be at least 1 block long. if (length < Aes.BlockSize) { throw new ArgumentException(); } var tweak = new Buffer16(); _tweakAesCore.Encrypt(Iv, tweak); using var tweakBuffer = new RentedArray <byte>(blockCount * Aes.BlockSize); tweak = FillTweakBuffer(tweak, MemoryMarshal.Cast <byte, Buffer16>(tweakBuffer.Span)); Utilities.XorArrays(output, input, tweakBuffer.Span); _dataAesCore.Encrypt(output.Slice(0, blockCount * Aes.BlockSize), output); Utilities.XorArrays(output, output, tweakBuffer.Array); if (leftover != 0) { Buffer16 inBlock = Unsafe.Add(ref Unsafe.As <byte, Buffer16>(ref MemoryMarshal.GetReference(input)), blockCount); ref Buffer16 outBlock = ref Unsafe.Add(ref Unsafe.As <byte, Buffer16>(ref MemoryMarshal.GetReference(output)), blockCount); ref Buffer16 prevOutBlock = ref Unsafe.Subtract(ref outBlock, 1);
private void DecryptHeader(ReadOnlySpan <byte> key, ref Package2Meta source, ref Package2Meta dest) { Buffer16 iv = source.HeaderIv; Aes.DecryptCtr128(SpanHelpers.AsByteSpan(ref source), SpanHelpers.AsByteSpan(ref dest), key, iv); // Copy the IV to the output because the IV field will be garbage after "decrypting" it Unsafe.As <Package2Meta, Buffer16>(ref dest) = iv; }
public static void CastBufferToSpan() { var buffer = new Buffer16(); Span <ulong> ulongSpan = buffer.AsSpan <ulong>(); Assert.Equal(2, ulongSpan.Length); Assert.True(Unsafe.AreSame(ref Unsafe.As <Buffer16, ulong>(ref buffer), ref ulongSpan[0])); }
public static void CastBufferToReadOnlyByteSpanImplicit() { var buffer = new Buffer16(); ReadOnlySpan <byte> byteSpan = buffer; Assert.Equal(16, byteSpan.Length); Assert.True(Unsafe.AreSame(ref Unsafe.As <Buffer16, byte>(ref buffer), ref Unsafe.AsRef(byteSpan[0]))); }
public static void CastBufferToByteSpan() { var buffer = new Buffer16(); Span <byte> byteSpan = buffer.Bytes; Assert.Equal(16, byteSpan.Length); Assert.True(Unsafe.AreSame(ref Unsafe.As <Buffer16, byte>(ref buffer), ref byteSpan[0])); }
public void Initialize(ReadOnlySpan <byte> key, ReadOnlySpan <byte> iv) { Debug.Assert(iv.Length == Aes.BlockSize); _aesCore = new AesCore(); _aesCore.Initialize(key, ReadOnlySpan <byte> .Empty, CipherMode.ECB, false); Iv = Unsafe.ReadUnaligned <Buffer16>(ref MemoryMarshal.GetReference(iv)); }
/// <summary> /// Computes the CMAC of the provided data using AES-128. /// </summary> /// <param name="mac">The buffer where the generated MAC will be placed. Must be at least 16 bytes long.</param> /// <param name="data">The message on which the MAC will be calculated.</param> /// <param name="key">The 128-bit AES key used to calculate the MAC.</param> /// <remarks>https://tools.ietf.org/html/rfc4493</remarks> public static void CalculateCmac(Span <byte> mac, ReadOnlySpan <byte> data, ReadOnlySpan <byte> key) { ReadOnlySpan <byte> zero = new Buffer16(); int len = data.Length; // Step 1, AES-128 with key K is applied to an all-zero input block. Span <byte> l = stackalloc byte[16]; EncryptCbc128(zero, l, key, zero); // Step 2, K1 is derived through the following operation: Span <byte> k1 = stackalloc byte[16]; LeftShiftBytes(l, k1); if ((l[0] & 0x80) == 0x80) // If the most significant bit of L is equal to 0, K1 is the left-shift of L by 1 bit. { k1[15] ^= 0x87; // Otherwise, K1 is the XOR of const_Rb and the left-shift of L by 1 bit. } // Step 3, K2 is derived through the following operation: Span <byte> k2 = stackalloc byte[16]; LeftShiftBytes(k1, k2); if ((k1[0] & 0x80) == 0x80) // If the most significant bit of K1 is equal to 0, K2 is the left-shift of K1 by 1 bit. { k2[15] ^= 0x87; // Otherwise, K2 is the XOR of const_Rb and the left-shift of K1 by 1 bit. } // ReSharper disable once RedundantAssignment Span <byte> paddedMessage = l; if (len != 0 && len % 16 == 0) // If the size of the input message block is equal to a positive multiple of the block size (namely, 128 bits), { // the last block shall be XOR'ed with K1 before processing paddedMessage = len < 0x800 ? stackalloc byte[len] : new byte[len]; data.CopyTo(paddedMessage); for (int j = 0; j < k1.Length; j++) { paddedMessage[paddedMessage.Length - 16 + j] ^= k1[j]; } } else // Otherwise, the last block shall be padded with 10^i and XOR'ed with K2. { int paddedLength = len + (16 - len % 16); paddedMessage = paddedLength < 0x800 ? stackalloc byte[paddedLength] : new byte[paddedLength]; paddedMessage.Slice(len).Clear(); paddedMessage[len] = 0x80; data.CopyTo(paddedMessage); for (int j = 0; j < k2.Length; j++) { paddedMessage[paddedMessage.Length - 16 + j] ^= k2[j]; } } EncryptCbc128(paddedMessage, paddedMessage, key, zero); // The result of the previous process will be the input of the last encryption. paddedMessage.Slice(paddedMessage.Length - 0x10).CopyTo(mac); }
public static void BufferIndexer() { var buffer = new Buffer16(); buffer[0] = 5; buffer[1] = 6; Assert.Equal(5, buffer[0]); Assert.Equal(6, buffer[1]); }
public long FindBackward(long start, ValueTuple <byte, byte>[] values) { return(FindBackward(start, Buffer16.CreateSearchData(values))); }
public override ISearchData CreateSearchData(IEnumerable <uint> values) { return(Buffer16.CreateSearchData(values.Select(a => new ValueTuple <byte, byte>( (byte)((a >> 8) & 0xFF), (byte)(a & 0xFF))).ToArray())); }
public static void CastBufferToStruct() { var buffer = new Buffer16(); ref ulong ulongSpan = ref buffer.As <ulong>();
public BitStream128(Buffer16 data) { _data = data; BitsLeft = 128; }