예제 #1
0
파일: Package1.cs 프로젝트: Icyelut/LibHac
        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));
        }
예제 #2
0
파일: Package1.cs 프로젝트: Icyelut/LibHac
        private Result SetPk11Storage()
        {
            // Read the PK11 header from the body storage
            int pk11Offset = IsModern ? ModernStage1Size : LegacyStage1Size;

            Result rc = BodyStorage.Read(pk11Offset, SpanHelpers.AsByteSpan(ref _pk11Header));

            if (rc.IsFailure())
            {
                return(rc);
            }

            // Check if PK11 is already decrypted, creating the PK11 storage if it is
            IsDecrypted = _pk11Header.Magic == Package1Pk11Header.ExpectedMagic;

            if (IsDecrypted)
            {
                Pk11Storage = new SubStorage(BodyStorage, pk11Offset, Pk11Size);
                return(Result.Success);
            }

            var encPk11Storage = new SubStorage(BodyStorage, pk11Offset, Pk11Size);

            // See if we have an Erista package1 key that can decrypt this PK11
            if (!IsMariko && TryFindEristaKeyRevision())
            {
                IsDecrypted = true;
                IStorage decPk11Storage;

                if (IsModern)
                {
                    decPk11Storage = new AesCbcStorage(encPk11Storage, KeySet.Package1Keys[KeyRevision],
                                                       _stage1Footer.Iv, true);
                }
                else
                {
                    decPk11Storage = new Aes128CtrStorage(encPk11Storage,
                                                          KeySet.Package1Keys[KeyRevision].DataRo.ToArray(), _stage1Footer.Iv.ToArray(), true);
                }

                Pk11Storage = new CachedStorage(decPk11Storage, 0x4000, 1, true);

                return(Result.Success);
            }

            // We can't decrypt the PK11. Set Pk11Storage to the encrypted PK11 storage
            Pk11Storage = encPk11Storage;
            return(Result.Success);
        }
예제 #3
0
파일: Package1.cs 프로젝트: Icyelut/LibHac
        /// <summary>
        /// Read the encrypted section of a Mariko Package1 and try to decrypt it.
        /// </summary>
        /// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
        /// <see cref="ResultLibHac.InvalidPackage1MarikoBodySize"/>: The package1 is
        /// too small or the size in the OEM header is incorrect.</returns>
        private Result InitMarikoBodyStorage()
        {
            // Body must be large enough to hold at least one metadata struct
            if (MarikoOemHeader.Size < Unsafe.SizeOf <Package1MetaData>())
            {
                return(ResultLibHac.InvalidPackage1MarikoBodySize.Log());
            }

            // Verify the body storage size is not smaller than the size in the header
            Result rc = BaseStorage.GetSize(out long totalSize);

            if (rc.IsFailure())
            {
                return(rc);
            }

            long bodySize = totalSize - Unsafe.SizeOf <Package1MarikoOemHeader>();

            if (bodySize < MarikoOemHeader.Size)
            {
                return(ResultLibHac.InvalidPackage1MarikoBodySize.Log());
            }

            // Create body SubStorage and metadata buffers
            var bodySubStorage = new SubStorage(BaseStorage, Unsafe.SizeOf <Package1MarikoOemHeader>(), bodySize);

            Span <Package1MetaData> metaData  = stackalloc Package1MetaData[2];
            Span <byte>             metaData1 = SpanHelpers.AsByteSpan(ref metaData[0]);
            Span <byte>             metaData2 = SpanHelpers.AsByteSpan(ref metaData[1]);

            // Read both the plaintext metadata and encrypted metadata
            rc = bodySubStorage.Read(0, MemoryMarshal.Cast <Package1MetaData, byte>(metaData));
            if (rc.IsFailure())
            {
                return(rc);
            }

            // Set the body storage and decrypted metadata
            _metaData   = metaData[0];
            BodyStorage = bodySubStorage;

            // The plaintext metadata is followed by an encrypted copy
            // If these two match then the body is already decrypted
            IsDecrypted = metaData1.SequenceEqual(metaData2);

            if (IsDecrypted)
            {
                return(Result.Success);
            }

            // If encrypted, check if the body can be decrypted
            Crypto.Aes.DecryptCbc128(metaData2, metaData2, KeySet.MarikoBek, _metaData.Iv);
            IsDecrypted = metaData2.SequenceEqual(SpanHelpers.AsByteSpan(ref _metaData));

            // Get a decrypted body storage if we have the correct key
            if (IsDecrypted)
            {
                var decStorage = new AesCbcStorage(bodySubStorage, KeySet.MarikoBek, _metaData.Iv, true);
                BodyStorage = new CachedStorage(decStorage, 0x4000, 1, true);
            }

            return(Result.Success);
        }