From ee04bcdc8d44cd946cba1f9c1fa57eb0c9ec207a Mon Sep 17 00:00:00 2001 From: jakcron Date: Sun, 15 Apr 2018 10:40:22 +0800 Subject: [PATCH] [nx] Add NcaUtils --- lib/libnx/include/nx/NcaUtils.h | 13 +++++++++ lib/libnx/source/NcaUtils.cpp | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 lib/libnx/include/nx/NcaUtils.h create mode 100644 lib/libnx/source/NcaUtils.cpp diff --git a/lib/libnx/include/nx/NcaUtils.h b/lib/libnx/include/nx/NcaUtils.h new file mode 100644 index 0000000..81f7163 --- /dev/null +++ b/lib/libnx/include/nx/NcaUtils.h @@ -0,0 +1,13 @@ +#pragma once +#include + +namespace nx +{ + class NcaUtils + { + public: + static inline size_t sectorToOffset(size_t sector_index) { return sector_index * nx::nca::kSectorSize; } + static void decryptNcaHeader(const byte_t* src, byte_t* dst, const crypto::aes::sAesXts128Key& key); + static byte_t getMasterKeyRevisionFromKeyGeneration(byte_t key_generation); + }; +} \ No newline at end of file diff --git a/lib/libnx/source/NcaUtils.cpp b/lib/libnx/source/NcaUtils.cpp new file mode 100644 index 0000000..145ccdf --- /dev/null +++ b/lib/libnx/source/NcaUtils.cpp @@ -0,0 +1,49 @@ +#include + +void nx::NcaUtils::decryptNcaHeader(const byte_t* src, byte_t* dst, const crypto::aes::sAesXts128Key& key) +{ + byte_t tweak[crypto::aes::kAesBlockSize]; + + // decrypt main header + byte_t raw_hdr[nx::nca::kSectorSize]; + crypto::aes::AesXtsMakeTweak(tweak, 1); + crypto::aes::AesXtsDecryptSector(src + sectorToOffset(1), nx::nca::kSectorSize, key.key[0], key.key[1], tweak, raw_hdr); + + bool useNca2SectorIndex = memcmp(((nx::sNcaHeader*)(raw_hdr))->signature, nx::nca::kNca2Sig.c_str(), 4) == 0; + + // decrypt whole header + for (size_t i = 0; i < nx::nca::kHeaderSectorNum; i++) + { + crypto::aes::AesXtsMakeTweak(tweak, (i > 1 && useNca2SectorIndex)? 0 : i); + crypto::aes::AesXtsDecryptSector(src + sectorToOffset(i), nx::nca::kSectorSize, key.key[0], key.key[1], tweak, dst + sectorToOffset(i)); + } +} + +byte_t nx::NcaUtils::getMasterKeyRevisionFromKeyGeneration(byte_t key_generation) +{ + byte_t masterkey_rev; + + switch (key_generation) + { + case(0): + case(1): + masterkey_rev = 0; + break; + case(2): + masterkey_rev = 1; + break; + case(3): + masterkey_rev = 2; + break; + case(4): + masterkey_rev = 3; + break; + case(5): + masterkey_rev = 4; + break; + default: + masterkey_rev = key_generation - 1; + } + + return masterkey_rev; +} \ No newline at end of file