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)); }
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); }
/// <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); }