Skip to content

Commit

Permalink
Configure keys file path from environment variable (#1)
Browse files Browse the repository at this point in the history
* fix ns_extract scripts:
 - add required length argument to to_bytes function
* use environment variable NSTOOLS_KEYS_FILE to configure keys file
* don't load keys by default, custom file can be provided
  • Loading branch information
a1ex4 authored Nov 9, 2023
1 parent 336f17d commit 609f3d4
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 38 deletions.
7 changes: 6 additions & 1 deletion py/ns_extract_hashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@

INCP_PATH = args.input

Pfs0.Keys.load_default()
if not Pfs0.Keys.keys_loaded:
input("Press Enter to exit...")
sys.exit(1)

def send_hook(message_content):
try:
print(message_content)
Expand All @@ -52,7 +57,7 @@ def scan_file():
if isinstance(section, Pfs0.Pfs0):
Cnmt = section.getCnmt()
for entry in Cnmt.contentEntries:
entryType = FsTools.get_metacontent_type(hx(entry.type.to_bytes(byteorder = 'big')))
entryType = FsTools.get_metacontent_type(hx(entry.type.to_bytes(length=(min(entry.type.bit_length(), 1) + 7) // 8, byteorder = 'big')))
print(f'\n:{Cnmt.titleId} - Content.{entryType}')
print(f'> NCA ID: {entry.ncaId}')
print(f'> HASH: {entry.hash.hex()}')
Expand Down
9 changes: 7 additions & 2 deletions py/ns_extract_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

INCP_PATH = args.input

Pfs0.Keys.load_default()
if not Pfs0.Keys.keys_loaded:
input("Press Enter to exit...")
sys.exit(1)

def send_hook(message_content):
try:
print(message_content)
Expand All @@ -53,15 +58,15 @@ def scan_file():
if isinstance(section, Pfs0.Pfs0):
Cnmt = section.getCnmt()

titleType = FsTools.parse_cnmt_type_n(hx(Cnmt.titleType.to_bytes(byteorder = 'big')))
titleType = FsTools.parse_cnmt_type_n(hx(Cnmt.titleType.to_bytes(length=(min(Cnmt.titleType.bit_length(), 1) + 7) // 8, byteorder = 'big')))

print(f'\n:: CNMT: {Cnmt._path}\n')
print(f'Title ID: {Cnmt.titleId.upper()}')
print(f'Version: {Cnmt.version}')
print(f'Title Type: {titleType}')

for entry in Cnmt.contentEntries:
entryType = FsTools.get_metacontent_type(hx(entry.type.to_bytes(byteorder = 'big')))
entryType = FsTools.get_metacontent_type(hx(entry.type.to_bytes(length=(min(entry.type.bit_length(), 1) + 7) // 8, byteorder = 'big')))
print(f'\n:{Cnmt.titleId} - Content.{entryType}')
print(f'> NCA ID: {entry.ncaId}')
print(f'> HASH: {entry.hash.hex()}')
Expand Down
5 changes: 5 additions & 0 deletions py/ns_verify_folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
WHOOK_URL = args.webhook_url
SAVE_VLOG = bool(args.save_log)

Verify.VerifyTools.Keys.load_default()
if not Verify.VerifyTools.Keys.keys_loaded:
input("Press Enter to exit...")
sys.exit(1)

def send_hook(message_content: str = '', PadPrint: bool = False):
if message_content == '':
return
Expand Down
75 changes: 40 additions & 35 deletions py/nut/Keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
titleKeks = []
keyAreaKeys = []
loadedKeysFile = "non-existing prod.keys/keys.txt"
keys_loaded = False

#This are NOT the keys but only a 4 bytes long checksum!
#See https://en.wikipedia.org/wiki/Cyclic_redundancy_check
Expand Down Expand Up @@ -125,6 +126,7 @@ def load(fileName):
global keyAreaKeys
global titleKeks
global loadedKeysFile
global keys_loaded
loadedKeysFile = fileName

with open(fileName, encoding="utf8") as f:
Expand Down Expand Up @@ -154,43 +156,46 @@ def load(fileName):
keyAreaKeys[i][1] = generateKek(key_area_key_ocean_source, masterKey, aes_kek_generation_source, aes_key_generation_source)
keyAreaKeys[i][2] = generateKek(key_area_key_system_source, masterKey, aes_kek_generation_source, aes_key_generation_source)

return True
keys_loaded = True
return keys_loaded
except BaseException as e:
Print.error(format_exc())
Print.error(str(e))

return False


keyPyPath = Path(sys.argv[0])
while not keyPyPath.is_dir():
keyPyPath = keyPyPath.parents[0]
keyRootPath = Path(os.path.abspath(os.path.join(str(keyPyPath), '..')))

keyfiles = [
Path.home().joinpath(".switch", "prod.keys"),
Path.home().joinpath(".switch", "keys.txt"),
keyRootPath.joinpath("prod.keys"),
keyRootPath.joinpath("keys.txt"),
keyPyPath.joinpath("prod.keys"),
keyPyPath.joinpath("keys.txt"),
]

loaded = False
for kf in keyfiles:
if kf.is_file():
loaded = load(str(kf))
if loaded == True:
print(f'[:INFO:] Keys Loaded: {str(kf)}')
break

if loaded == False:
errorMsg = ""
keys_loaded = False
return keys_loaded

def load_default():
keyPyPath = Path(sys.argv[0])
while not keyPyPath.is_dir():
keyPyPath = keyPyPath.parents[0]
keyRootPath = Path(os.path.abspath(os.path.join(str(keyPyPath), '..')))

keyfiles = [
Path.home().joinpath(".switch", "prod.keys"),
Path.home().joinpath(".switch", "keys.txt"),
keyRootPath.joinpath("prod.keys"),
keyRootPath.joinpath("keys.txt"),
keyPyPath.joinpath("prod.keys"),
keyPyPath.joinpath("keys.txt"),
Path(os.environ.get("NSTOOLS_KEYS_FILE", "$NSTOOLS_KEYS_FILE")),
]

keys_loaded = False
for kf in keyfiles:
if errorMsg != "":
errorMsg += "\nor "
errorMsg += f"{str(kf)}"
errorMsg += " not found\n\nPlease dump your keys using https://github.com/shchmue/Lockpick_RCM/releases\n"
Print.error(errorMsg)
input("Press Enter to exit...")
sys.exit(1)
if kf.is_file():
keys_loaded = load(str(kf))
if keys_loaded == True:
print(f'[:INFO:] Keys Loaded: {str(kf)}')
break

if keys_loaded == False:
errorMsg = ""
for kf in keyfiles:
if errorMsg != "":
errorMsg += "\nor "
errorMsg += f"{str(kf)}"
errorMsg += " not found\n\nPlease dump your keys using https://github.com/shchmue/Lockpick_RCM/releases\n"
errorMsg = "Failed to load default keys files:\n" + errorMsg
Print.error(errorMsg)
return keys_loaded

0 comments on commit 609f3d4

Please sign in to comment.