private void DecryptKeyblobs(IProgressReport logger = null) { var cmac = new byte[0x10]; var expectedCmac = new byte[0x10]; var counter = new byte[0x10]; for (int i = 0; i < UsedKeyblobCount; i++) { if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty()) { continue; } Array.Copy(EncryptedKeyblobs[i], expectedCmac, 0x10); CryptoOld.CalculateAesCmac(KeyblobMacKeys[i], EncryptedKeyblobs[i], 0x10, cmac, 0, 0xa0); if (!Util.ArraysEqual(cmac, expectedCmac)) { logger?.LogMessage($"Warning: Keyblob MAC {i:x2} is invalid. Are SBK/TSEC key correct?"); } Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10); Aes.DecryptCtr128(EncryptedKeyblobs[i].AsSpan(0x20), Keyblobs[i], KeyblobKeys[i], counter); } }
private void DecryptKeyblobs(IProgressReport logger = null) { var cmac = new byte[0x10]; var expectedCmac = new byte[0x10]; var counter = new byte[0x10]; for (int i = 0; i < UsedKeyblobCount; i++) { if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty()) { continue; } Array.Copy(EncryptedKeyblobs[i], expectedCmac, 0x10); CryptoOld.CalculateAesCmac(KeyblobMacKeys[i], EncryptedKeyblobs[i], 0x10, cmac, 0, 0xa0); if (!Util.ArraysEqual(cmac, expectedCmac)) { logger?.LogMessage($"Warning: Keyblob MAC {i:x2} is invalid. Are SBK/TSEC key correct?"); } Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10); using (var keyblobDec = new Aes128CtrStorage( new MemoryStorage(EncryptedKeyblobs[i], 0x20, Keyblobs[i].Length), KeyblobKeys[i], counter, false)) { keyblobDec.Read(0, Keyblobs[i]).ThrowIfFailure(); } } }
public byte[] GetTitleKey(KeySet keySet) { if (TitleKeyType == TitleKeyType.Common) { var commonKey = new byte[0x10]; Array.Copy(TitleKeyBlock, commonKey, commonKey.Length); return(commonKey); } return(CryptoOld.DecryptRsaOaep(TitleKeyBlock, keySet.ETicketExtKeyRsa)); }
public Package2Header(IStorage storage, Keyset keyset, int keyGeneration) { var reader = new BinaryReader(storage.AsStream()); byte[] key = keyset.Package2Keys[keyGeneration]; Signature = reader.ReadBytes(0x100); byte[] sigData = reader.ReadBytes(0x100); SignatureValidity = CryptoOld.Rsa2048PssVerify(sigData, Signature, keyset.Package2FixedKeyModulus); reader.BaseStream.Position -= 0x100; Counter = reader.ReadBytes(0x10); Stream headerStream = new CachedStorage(new Aes128CtrStorage(storage.Slice(0x100), key, Counter, true), 0x4000, 4, true).AsStream(); headerStream.Position = 0x10; reader = new BinaryReader(headerStream); for (int i = 0; i < 4; i++) { SectionCounters[i] = reader.ReadBytes(0x10); } Magic = reader.ReadAscii(4); BaseOffset = reader.ReadInt32(); reader.BaseStream.Position += 4; VersionMax = reader.ReadByte(); VersionMin = reader.ReadByte(); reader.BaseStream.Position += 2; for (int i = 0; i < 4; i++) { SectionSizes[i] = reader.ReadInt32(); } for (int i = 0; i < 4; i++) { SectionOffsets[i] = reader.ReadInt32(); } for (int i = 0; i < 4; i++) { SectionHashes[i] = reader.ReadBytes(0x20); } }
public XciHeader(KeySet keySet, Stream stream) { using (var reader = new BinaryReader(stream, Encoding.Default, true)) { Signature = reader.ReadBytes(SignatureSize); Magic = reader.ReadAscii(4); if (Magic != HeaderMagic) { throw new InvalidDataException("Invalid XCI file: Header magic invalid."); } reader.BaseStream.Position = SignatureSize; byte[] sigData = reader.ReadBytes(SignatureSize); reader.BaseStream.Position = SignatureSize + 4; SignatureValidity = CryptoOld.Rsa2048Pkcs1Verify(sigData, Signature, _xciHeaderPubk); RomAreaStartPage = reader.ReadInt32(); BackupAreaStartPage = reader.ReadInt32(); byte keyIndex = reader.ReadByte(); KekIndex = (byte)(keyIndex >> 4); TitleKeyDecIndex = (byte)(keyIndex & 7); GameCardSize = (GameCardSizeInternal)reader.ReadByte(); CardHeaderVersion = reader.ReadByte(); Flags = (GameCardAttribute)reader.ReadByte(); PackageId = reader.ReadUInt64(); ValidDataEndPage = reader.ReadInt64(); AesCbcIv = reader.ReadBytes(Aes.KeySize128); Array.Reverse(AesCbcIv); RootPartitionOffset = reader.ReadInt64(); RootPartitionHeaderSize = reader.ReadInt64(); RootPartitionHeaderHash = reader.ReadBytes(Sha256.DigestSize); InitialDataHash = reader.ReadBytes(Sha256.DigestSize); SelSec = reader.ReadInt32(); SelT1Key = reader.ReadInt32(); SelKey = reader.ReadInt32(); LimAreaPage = reader.ReadInt32(); if (keySet != null && !keySet.XciHeaderKey.IsZeros()) { byte[] encHeader = reader.ReadBytes(EncryptedHeaderSize); byte[] decHeader = new byte[EncryptedHeaderSize]; Aes.DecryptCbc128(encHeader, decHeader, keySet.XciHeaderKey, AesCbcIv); using (var decReader = new BinaryReader(new MemoryStream(decHeader))) { FwVersion = decReader.ReadUInt64(); AccCtrl1 = (CardClockRate)decReader.ReadInt32(); Wait1TimeRead = decReader.ReadInt32(); Wait2TimeRead = decReader.ReadInt32(); Wait1TimeWrite = decReader.ReadInt32(); Wait2TimeWrite = decReader.ReadInt32(); FwMode = decReader.ReadInt32(); UppVersion = decReader.ReadInt32(); decReader.BaseStream.Position += 4; UppHash = decReader.ReadBytes(8); UppId = decReader.ReadUInt64(); } } ImageHash = new byte[Sha256.DigestSize]; Sha256.GenerateSha256Hash(sigData, ImageHash); reader.BaseStream.Position = RootPartitionOffset; byte[] headerBytes = reader.ReadBytes((int)RootPartitionHeaderSize); Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize]; Sha256.GenerateSha256Hash(headerBytes, actualHeaderHash); PartitionFsHeaderValidity = Utilities.SpansEqual(RootPartitionHeaderHash, actualHeaderHash) ? Validity.Valid : Validity.Invalid; } }