Skip to content

Instantly share code, notes, and snippets.

@TooTallNate
Last active December 30, 2024 07:09
Show Gist options
  • Save TooTallNate/4fa19e9c8aa567d6a6b82e87751d3065 to your computer and use it in GitHub Desktop.
Save TooTallNate/4fa19e9c8aa567d6a6b82e87751d3065 to your computer and use it in GitHub Desktop.
Get the NCA header decryption key in nx.js
// These source values are seen in other open source repos:
// - https://github.com/blawar/tinleaf/blob/3363538600e47e1862d64d265dab1a031b32d037/include/util/crypto.hpp#L41-L42
// - https://github.com/ITotalJustice/sphaira/blob/0370e47f7fac0e426675624f363fe50f3b442048/sphaira/source/owo.cpp#L339-L346
const headerKekSource = new Uint8Array([
0x1f, 0x12, 0x91, 0x3a, 0x4a, 0xcb, 0xf0, 0x0d, 0x4c, 0xde, 0x3a, 0xf6,
0xd5, 0x23, 0x88, 0x2a,
]);
const headerKeySource = new Uint8Array([
0x5a, 0x3e, 0xd8, 0x4f, 0xde, 0xc0, 0xd8, 0x26, 0x31, 0xf7, 0xe2, 0x5d,
0x19, 0x7b, 0xf5, 0xd0, 0x1c, 0x9b, 0x7b, 0xfa, 0xf6, 0x28, 0x18, 0x3d,
0x71, 0xf6, 0x4d, 0x73, 0xf1, 0x50, 0xb9, 0xd2,
]);
const kek = splCryptoGenerateAesKek(headerKekSource.buffer, 0, 0);
const key0 = splCryptoGenerateAesKey(
kek,
headerKeySource.buffer.slice(0, 0x10),
);
const key1 = splCryptoGenerateAesKey(kek, headerKeySource.buffer.slice(0x10));
const key = new Uint8Array([
...new Uint8Array(key0),
...new Uint8Array(key1),
]);
const splMig = new Switch.Service('spl:mig');
export function splCryptoGenerateAesKek(
wrappedKek: ArrayBuffer,
keyGeneration: number,
option: number,
): ArrayBuffer {
//Result splCryptoGenerateAesKek(const void *wrapped_kek, u32 key_generation, u32 option, void *out_sealed_kek) {
// const struct {
// SplKey wrapped_kek;
// u32 key_generation;
// u32 option;
// } in = { *((const SplKey *)wrapped_kek), key_generation, option };
// return serviceDispatchInOut(_splGetCryptoSrv(), 2, in, *((SplKey *)out_sealed_kek));
//}
const inData = new Uint8Array(0x18);
inData.set(new Uint8Array(wrappedKek, 0, 0x10), 0);
const inDataArr = new Uint32Array(inData.buffer, 0x10, 2);
inDataArr[0] = keyGeneration;
inDataArr[1] = option;
const out = new Uint8Array(0x10);
splMig.dispatchInOut(2, inData.buffer, out.buffer);
return out;
}
export function splCryptoGenerateAesKey(
sealedKek: ArrayBuffer,
wrappedKey: ArrayBuffer,
): ArrayBuffer {
//Result splCryptoGenerateAesKey(const void *sealed_kek, const void *wrapped_key, void *out_sealed_key) {
// const struct {
// SplKey sealed_kek;
// SplKey wrapped_key;
// } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key) };
// return serviceDispatchInOut(_splGetCryptoSrv(), 4, in, *((SplKey *)out_sealed_key));
//}
const inData = new Uint8Array(0x20);
inData.set(new Uint8Array(sealedKek, 0, 0x10), 0);
inData.set(new Uint8Array(wrappedKey, 0, 0x10), 0x10);
const out = new Uint8Array(0x10);
splMig.dispatchInOut(4, inData.buffer, out.buffer);
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment