Example #1
0
        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));
        }
Example #2
0
        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);
Example #3
0
        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;
        }
Example #4
0
        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]));
        }
Example #5
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])));
        }
Example #6
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]));
        }
Example #7
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));
        }
Example #8
0
        /// <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);
        }
Example #9
0
        public static void BufferIndexer()
        {
            var buffer = new Buffer16();

            buffer[0] = 5;
            buffer[1] = 6;

            Assert.Equal(5, buffer[0]);
            Assert.Equal(6, buffer[1]);
        }
Example #10
0
 public long FindBackward(long start, ValueTuple <byte, byte>[] values)
 {
     return(FindBackward(start, Buffer16.CreateSearchData(values)));
 }
Example #11
0
 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()));
 }
Example #12
0
        public static void CastBufferToStruct()
        {
            var buffer = new Buffer16();

            ref ulong ulongSpan = ref buffer.As <ulong>();
Example #13
0
 public BitStream128(Buffer16 data)
 {
     _data    = data;
     BitsLeft = 128;
 }