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); Crypto.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(Keyblobs[i], 0); } } }
private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index) { NcaFsHeader fsHeader = Header.GetFsHeader(index); NcaFsPatchInfo info = fsHeader.GetPatchInfo(); long sectionOffset = Header.GetSectionStartOffset(index); long sectionSize = Header.GetSectionSize(index); long bktrOffset = info.RelocationTreeOffset; long bktrSize = sectionSize - bktrOffset; long dataSize = info.RelocationTreeOffset; byte[] key = GetContentKey(NcaKeyType.AesCtr); byte[] counter = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset); byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset); IStorage bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); IStorage encryptionBucketTreeData = bucketTreeData.Slice(info.EncryptionTreeOffset - bktrOffset); IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), encryptionBucketTreeData, key, counterEx, true); decStorage = new CachedStorage(decStorage, 0x4000, 4, true); return(new ConcatenationStorage(new[] { decStorage, bucketTreeData }, true)); }
public static RSAParameters DecryptRsaKey(byte[] encryptedKey, byte[] kek) { var counter = new byte[0x10]; Array.Copy(encryptedKey, counter, 0x10); var body = new byte[0x230]; Array.Copy(encryptedKey, 0x10, body, 0, 0x230); var dec = new byte[0x230]; using (var storageDec = new Aes128CtrStorage(new MemoryStorage(body), kek, counter, false)) { storageDec.Read(dec, 0); } var d = new byte[0x100]; var n = new byte[0x100]; var e = new byte[4]; Array.Copy(dec, 0, d, 0, 0x100); Array.Copy(dec, 0x100, n, 0, 0x100); Array.Copy(dec, 0x200, e, 0, 4); BigInteger dInt = GetBigInteger(d); BigInteger nInt = GetBigInteger(n); BigInteger eInt = GetBigInteger(e); RSAParameters rsaParams = RecoverRsaParameters(nInt, eInt, dInt); TestRsaKey(rsaParams); return(rsaParams); }
public static void Process(Context ctx) { switch (ctx.Options.BenchType?.ToLower()) { case "aesctr": { IStorage decStorage = new MemoryStorage(new byte[Size]); IStorage encStorage = new Aes128CtrStorage(new MemoryStorage(new byte[Size]), new byte[0x10], new byte[0x10], true); CopyBenchmark(decStorage, encStorage, Iterations, "MemoryStorage Encrypt: ", ctx.Logger); CopyBenchmark(encStorage, decStorage, Iterations, "MemoryStorage Decrypt: ", ctx.Logger); decStorage = new NullStorage(Size); encStorage = new Aes128CtrStorage(new NullStorage(Size), new byte[0x10], new byte[0x10], true); CopyBenchmark(decStorage, encStorage, Iterations, "NullStorage Encrypt: ", ctx.Logger); CopyBenchmark(encStorage, decStorage, Iterations, "NullStorage Decrypt: ", ctx.Logger); decStorage = new MemoryStorage(new byte[Size]); encStorage = new CachedStorage(new Aes128CtrStorage(new MemoryStorage(new byte[Size]), new byte[0x10], new byte[0x10], true), 0x4000, 4, true); CopyBenchmark(decStorage, encStorage, Iterations, "CachedStorage Encrypt: ", ctx.Logger); CopyBenchmark(encStorage, decStorage, Iterations, "CachedStorage Decrypt: ", ctx.Logger); break; } case "aesxts": { IStorage decStorage = new MemoryStorage(new byte[Size]); IStorage encStorage = new Aes128XtsStorage(new MemoryStorage(new byte[Size]), new byte[0x20], 81920, true); CopyBenchmark(decStorage, encStorage, Iterations, "MemoryStorage Encrypt: ", ctx.Logger); CopyBenchmark(encStorage, decStorage, Iterations, "MemoryStorage Decrypt: ", ctx.Logger); decStorage = new NullStorage(Size); encStorage = new Aes128XtsStorage(new NullStorage(Size), new byte[0x20], 81920, true); CopyBenchmark(decStorage, encStorage, Iterations, "NullStorage Encrypt: ", ctx.Logger); CopyBenchmark(encStorage, decStorage, Iterations, "NullStorage Decrypt: ", ctx.Logger); decStorage = new MemoryStorage(new byte[Size]); encStorage = new CachedStorage(new Aes128XtsStorage(new MemoryStorage(new byte[Size]), new byte[0x20], 0x4000, true), 4, true); CopyBenchmark(decStorage, encStorage, Iterations, "CachedStorage Encrypt: ", ctx.Logger); CopyBenchmark(encStorage, decStorage, Iterations, "CachedStorage Decrypt: ", ctx.Logger); break; } default: ctx.Logger.LogMessage("Unknown benchmark type."); return; } }
// ReSharper restore UnusedParameter.Local private IStorage OpenAesCtrStorage(IStorage baseStorage, int index) { NcaFsHeader fsHeader = Header.GetFsHeader(index); byte[] key = GetContentKey(NcaKeyType.AesCtr); byte[] counter = Aes128CtrStorage.CreateCounter(fsHeader.Counter, Header.GetSectionStartOffset(index)); var aesStorage = new Aes128CtrStorage(baseStorage, key, Header.GetSectionStartOffset(index), counter, true); return(new CachedStorage(aesStorage, 0x4000, 4, true)); }
private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index, bool decrypting) { NcaFsHeader fsHeader = GetFsHeader(index); NcaFsPatchInfo info = fsHeader.GetPatchInfo(); long sectionOffset = Header.GetSectionStartOffset(index); long sectionSize = Header.GetSectionSize(index); long bktrOffset = info.RelocationTreeOffset; long bktrSize = sectionSize - bktrOffset; long dataSize = info.RelocationTreeOffset; byte[] key = GetContentKey(NcaKeyType.AesCtr); byte[] counter = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset); byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset); IStorage bucketTreeData; IStorage outputBucketTreeData; if (decrypting) { bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); outputBucketTreeData = bucketTreeData; } else { bucketTreeData = baseStorage.Slice(bktrOffset, bktrSize); outputBucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); } var encryptionBucketTreeData = new SubStorage(bucketTreeData, info.EncryptionTreeOffset - bktrOffset, sectionSize - info.EncryptionTreeOffset); var cachedBucketTreeData = new CachedStorage(encryptionBucketTreeData, IndirectStorage.NodeSize, 6, true); var treeHeader = new BucketTree.Header(); info.EncryptionTreeHeader.CopyTo(SpanHelpers.AsByteSpan(ref treeHeader)); long nodeStorageSize = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount); long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount); var tableNodeStorage = new SubStorage(cachedBucketTreeData, 0, nodeStorageSize); var tableEntryStorage = new SubStorage(cachedBucketTreeData, nodeStorageSize, entryStorageSize); IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), tableNodeStorage, tableEntryStorage, treeHeader.EntryCount, key, counterEx, true); return(new ConcatenationStorage(new[] { decStorage, outputBucketTreeData }, 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); }
private int FindKeyGeneration(Keyset keyset, IStorage storage) { var counter = new byte[0x10]; var decBuffer = new byte[0x10]; storage.Read(0x100, counter).ThrowIfFailure(); for (int i = 0; i < 0x20; i++) { var dec = new Aes128CtrStorage(storage.Slice(0x100), keyset.Package2Keys[i], counter, false); dec.Read(0x50, decBuffer).ThrowIfFailure(); if (BitConverter.ToUInt32(decBuffer, 0) == Pk21Magic) { return(i); } } throw new InvalidDataException("Failed to decrypt package2! Is the correct key present?"); }
public Package1(KeySet keySet, IStorage storage) { Storage = storage; var reader = new BinaryReader(storage.AsStream()); BuildHash = reader.ReadBytes(0x10); BuildDate = reader.ReadAscii(0xE); Field1E = reader.ReadUInt16(); reader.BaseStream.Position = 0x3FE0; Pk11Size = reader.ReadInt32(); reader.BaseStream.Position += 0xC; Counter = reader.ReadBytes(0x10); // Try decrypting the PK11 blob with all known package1 keys IStorage encStorage = Storage.Slice(0x4000, Pk11Size); byte[] decBuffer = new byte[0x10]; for (int i = 0; i < 0x20; i++) { var dec = new Aes128CtrStorage(encStorage, keySet.Package1Keys[i].DataRo.ToArray(), Counter, true); dec.Read(0, decBuffer).ThrowIfFailure(); if (BitConverter.ToUInt32(decBuffer, 0) == Pk11Magic) { KeyRevision = i; Pk11 = new Pk11(new CachedStorage(dec, 4, true)); return; } } throw new InvalidDataException("Failed to decrypt PK11! Is the correct key present?"); }