mirror of
https://github.com/NinjaCheetah/WiiPy.git
synced 2025-04-26 13:21:01 -04:00
Joined all WAD re-encryption commands into "wad convert"
This commit is contained in:
parent
a4c06cae36
commit
530afd4189
@ -55,9 +55,11 @@ def build_cios(args):
|
||||
base_version = int(target_base.get("version"))
|
||||
if title.tmd.title_version != base_version:
|
||||
raise ValueError("The provided base IOS does not match the required version for this base!")
|
||||
print(f"Building cIOS \"{args.cios_ver}\" from base IOS{target_base.get('ios')} v{base_version}...")
|
||||
|
||||
# We're ready to begin building the cIOS now. Find all the <content> tags that have <patch> tags, and then apply
|
||||
# the patches listed in them to the content.
|
||||
print("Patching existing modules...")
|
||||
for content in target_base.findall("content"):
|
||||
patches = content.findall("patch")
|
||||
if patches:
|
||||
@ -90,6 +92,7 @@ def build_cios(args):
|
||||
title.set_content(dec_content, content_index, content_type=libWiiPy.title.ContentType.NORMAL)
|
||||
|
||||
# Next phase of cIOS building is to add the required extra modules.
|
||||
print("Adding required additional modules...")
|
||||
for content in target_base.findall("content"):
|
||||
target_module = content.get("module")
|
||||
if target_module is not None:
|
||||
@ -122,6 +125,7 @@ def build_cios(args):
|
||||
title.set_title_version(args.version)
|
||||
except ValueError:
|
||||
raise ValueError(f"The provided version \"{args.version}\" is not valid!")
|
||||
print(f"Set cIOS slot to \"{slot}\" and cIOS version to \"{args.version}\"!")
|
||||
|
||||
# If this is a vWii cIOS, then we need to re-encrypt it with the Wii Common key so that it's installable from
|
||||
# within Wii mode.
|
||||
@ -134,8 +138,6 @@ def build_cios(args):
|
||||
title.fakesign()
|
||||
|
||||
# Write the new cIOS to the specified output path.
|
||||
out_file = open(output_path, "wb")
|
||||
out_file.write(title.dump_wad())
|
||||
out_file.close()
|
||||
output_path.write_bytes(title.dump_wad())
|
||||
|
||||
print("success")
|
||||
print(f"Successfully built cIOS \"{args.cios_ver}\"!")
|
||||
|
@ -88,7 +88,10 @@ def _print_ticket_info(ticket: libWiiPy.title.Ticket):
|
||||
print(f" Certificate Info: {ticket.signature_issuer} (Unknown)")
|
||||
match ticket.common_key_index:
|
||||
case 0:
|
||||
key = "Common"
|
||||
if ticket.is_dev:
|
||||
key = "Common (Development)"
|
||||
else:
|
||||
key = "Common (Retail)"
|
||||
case 1:
|
||||
key = "Korean"
|
||||
case 2:
|
||||
|
@ -68,6 +68,75 @@ def handle_wad_add(args):
|
||||
print(f"Successfully added new content with Content ID \"{target_cid:08X}\" and type \"{target_type.name}\"!")
|
||||
|
||||
|
||||
def handle_wad_convert(args):
|
||||
input_path = pathlib.Path(args.input)
|
||||
if args.dev:
|
||||
target = "development"
|
||||
elif args.retail:
|
||||
target = "retail"
|
||||
elif args.vwii:
|
||||
target = "vWii"
|
||||
else:
|
||||
raise ValueError("No valid target was provided!")
|
||||
|
||||
if args.output is None:
|
||||
match target:
|
||||
case "development":
|
||||
output_path = pathlib.Path(input_path.stem + "_dev" + input_path.suffix)
|
||||
case "retail":
|
||||
output_path = pathlib.Path(input_path.stem + "_retail" + input_path.suffix)
|
||||
case "vWii":
|
||||
output_path = pathlib.Path(input_path.stem + "_vWii" + input_path.suffix)
|
||||
case _:
|
||||
raise ValueError("No valid target was provided!")
|
||||
else:
|
||||
output_path = pathlib.Path(args.output)
|
||||
|
||||
if not input_path.exists():
|
||||
raise FileNotFoundError(input_path)
|
||||
|
||||
title = libWiiPy.title.Title()
|
||||
title.load_wad(input_path.read_bytes())
|
||||
# First, verify that this WAD isn't already the type we're trying to convert to.
|
||||
if title.ticket.is_dev and target == "development":
|
||||
raise ValueError("This is already a development WAD!")
|
||||
elif not title.ticket.is_dev and not title.tmd.vwii and target == "retail":
|
||||
raise ValueError("This is already a retail WAD!")
|
||||
elif not title.ticket.is_dev and title.tmd.vwii and target == "vWii":
|
||||
raise ValueError("This is already a vWii WAD!")
|
||||
# Get the current type to display later.
|
||||
if title.ticket.is_dev:
|
||||
source = "development"
|
||||
elif title.tmd.vwii:
|
||||
source = "vWii"
|
||||
else:
|
||||
source = "retail"
|
||||
# Extract the Title Key so it can be re-encrypted with the correct key later.
|
||||
title_key = title.ticket.get_title_key()
|
||||
title_key_new = None
|
||||
if target == "development":
|
||||
# Set the development signature info.
|
||||
title.ticket.signature_issuer = "Root-CA00000002-XS00000006" + title.ticket.signature_issuer[26:]
|
||||
title.tmd.signature_issuer = "Root-CA00000002-CP00000007" + title.tmd.signature_issuer[26:]
|
||||
# Re-encrypt the title key with the dev key, and set that in the Ticket.
|
||||
title_key_new = libWiiPy.title.encrypt_title_key(title_key, 0, title.ticket.title_id, True)
|
||||
title.ticket.common_key_index = 0
|
||||
else:
|
||||
# Set the retail signature info.
|
||||
title.ticket.signature_issuer = "Root-CA00000001-XS00000003" + title.ticket.signature_issuer[26:]
|
||||
title.tmd.signature_issuer = "Root-CA00000001-CP00000004" + title.tmd.signature_issuer[26:]
|
||||
if target == "retail":
|
||||
title_key_new = libWiiPy.title.encrypt_title_key(title_key, 0, title.ticket.title_id, False)
|
||||
title.ticket.common_key_index = 0
|
||||
elif target == "vWii":
|
||||
title_key_new = libWiiPy.title.encrypt_title_key(title_key, 2, title.ticket.title_id, False)
|
||||
title.ticket.common_key_index = 2
|
||||
title.ticket.title_key_enc = title_key_new
|
||||
title.fakesign()
|
||||
output_path.write_bytes(title.dump_wad())
|
||||
print(f"Successfully converted {source} WAD to {target} WAD \"{output_path.name}\"!")
|
||||
|
||||
|
||||
def handle_wad_pack(args):
|
||||
input_path = pathlib.Path(args.input)
|
||||
output_path = pathlib.Path(args.output)
|
||||
@ -299,77 +368,3 @@ def handle_wad_unpack(args):
|
||||
output_path.joinpath(content_file_name).write_bytes(title.get_content_by_index(content_file, skip_hash))
|
||||
|
||||
print("WAD file unpacked!")
|
||||
|
||||
|
||||
def handle_wad_d2r(args):
|
||||
input_path = pathlib.Path(args.input)
|
||||
output_path = pathlib.Path(input_path.stem + "_retail" + input_path.suffix)
|
||||
|
||||
if not input_path.exists():
|
||||
raise FileNotFoundError(input_path)
|
||||
|
||||
title = libWiiPy.title.Title()
|
||||
title.load_wad(input_path.read_bytes())
|
||||
# First, verify that this IS actually a dev WAD.
|
||||
if not title.ticket.is_dev:
|
||||
raise ValueError("This is not a development WAD!")
|
||||
# Now, extract the Title Key, change the certs in the TMD/tik, and set the new retail-encrypted Title Key. The certs
|
||||
# need to be changed so that this WAD can be identified as retail later. The WAD will also be fakesigned, since
|
||||
# making this change invalidates the signature, so there's no downside.
|
||||
title_key = title.ticket.get_title_key()
|
||||
title.ticket.signature_issuer = "Root-CA00000001-XS00000003" + title.ticket.signature_issuer[26:]
|
||||
title_key_retail = libWiiPy.title.encrypt_title_key(title_key, 0, title.ticket.title_id, False)
|
||||
title.ticket.title_key_enc = title_key_retail
|
||||
title.tmd.signature_issuer = "Root-CA00000001-CP00000004" + title.tmd.signature_issuer[26:]
|
||||
title.fakesign()
|
||||
output_path.write_bytes(title.dump_wad())
|
||||
print(f"Successfully converted development WAD to retail WAD \"{output_path.name}\"!")
|
||||
|
||||
|
||||
def handle_wad_r2d(args):
|
||||
input_path = pathlib.Path(args.input)
|
||||
output_path = pathlib.Path(input_path.stem + "_dev" + input_path.suffix)
|
||||
|
||||
if not input_path.exists():
|
||||
raise FileNotFoundError(input_path)
|
||||
|
||||
title = libWiiPy.title.Title()
|
||||
title.load_wad(input_path.read_bytes())
|
||||
# First, verify that this IS actually a retail WAD.
|
||||
if title.ticket.is_dev:
|
||||
raise ValueError("This is not a retail WAD!")
|
||||
# Now, extract the Title Key, change the certs in the TMD/tik, and set the new dev-encrypted Title Key. The certs
|
||||
# need to be changed so that this WAD can be identified as dev later. The WAD will also be fakesigned, since making
|
||||
# this change invalidates the signature, so there's no downside.
|
||||
title_key = title.ticket.get_title_key()
|
||||
title.ticket.signature_issuer = "Root-CA00000002-XS00000006" + title.ticket.signature_issuer[26:]
|
||||
title_key_dev = libWiiPy.title.encrypt_title_key(title_key, 0, title.ticket.title_id, True)
|
||||
title.ticket.title_key_enc = title_key_dev
|
||||
title.tmd.signature_issuer = "Root-CA00000002-CP00000007" + title.tmd.signature_issuer[26:]
|
||||
title.fakesign()
|
||||
output_path.write_bytes(title.dump_wad())
|
||||
print(f"Successfully converted retail WAD to development WAD \"{output_path.name}\"!")
|
||||
|
||||
|
||||
def handle_wad_v2w(args):
|
||||
input_path = pathlib.Path(args.input)
|
||||
output_path = pathlib.Path(input_path.stem + "_Wii" + input_path.suffix)
|
||||
|
||||
if not input_path.exists():
|
||||
raise FileNotFoundError(input_path)
|
||||
|
||||
title = libWiiPy.title.Title()
|
||||
title.load_wad(input_path.read_bytes())
|
||||
# First, verify that this IS actually a vWii WAD.
|
||||
if title.ticket.common_key_index != 2:
|
||||
raise ValueError("This is not a vWii WAD!")
|
||||
# Now, extract the Title Key, change the required flags in the TMD/tik, and set the new common key encrypted
|
||||
# Title Key. The WAD will also be fakesigned, since making this change invalidates the signature, so there's no
|
||||
# downside.
|
||||
title_key_dec = title.ticket.get_title_key()
|
||||
title_key_common = libWiiPy.title.encrypt_title_key(title_key_dec, 0, title.tmd.title_id)
|
||||
title.ticket.title_key_enc = title_key_common
|
||||
title.ticket.common_key_index = 0
|
||||
title.fakesign()
|
||||
output_path.write_bytes(title.dump_wad())
|
||||
print(f"Successfully re-encrypted vWii WAD to regular WAD \"{output_path.name}\"!")
|
||||
|
39
wiipy.py
39
wiipy.py
@ -224,12 +224,26 @@ if __name__ == "__main__":
|
||||
"(optional, will default to \"Normal\" if not specified)")
|
||||
wad_add_parser.add_argument("-o", "--output", metavar="OUT", type=str,
|
||||
help="file to output the updated WAD to (optional)")
|
||||
# dev2retail WAD subcommand.
|
||||
wad_d2r_parser = wad_subparsers.add_parser("dev2retail", help="re-encrypt a dev WAD for retail consoles",
|
||||
description="re-encrypt a dev WAD for retail consoles, and update"
|
||||
"the certs to match; this also fakesigns the WAD")
|
||||
wad_d2r_parser.set_defaults(func=handle_wad_d2r)
|
||||
wad_d2r_parser.add_argument("input", metavar="IN", type=str, help="dev WAD file to re-encrypt")
|
||||
# Convert WAD subcommand.
|
||||
wad_convert_parser = wad_subparsers.add_parser("convert", help="re-encrypt a WAD file with a different key",
|
||||
description="re-encrypt a WAD file with a different key, making it "
|
||||
"possible to use the WAD in a different environment; "
|
||||
"this fakesigns the WAD by default")
|
||||
wad_convert_parser.set_defaults(func=handle_wad_convert)
|
||||
wad_convert_parser.add_argument("input", metavar="IN", type=str, help="WAD file to re-encrypt")
|
||||
wad_convert_targets_lbl = wad_convert_parser.add_argument_group(title="target keys")
|
||||
wad_convert_targets = wad_convert_targets_lbl.add_mutually_exclusive_group(required=True)
|
||||
wad_convert_targets.add_argument("-d", "--dev", action="store_true",
|
||||
help="re-encrypt the WAD with the development common key, allowing it to be "
|
||||
"installed on development consoles")
|
||||
wad_convert_targets.add_argument("-r", "--retail", action="store_true",
|
||||
help="re-encrypt the WAD with the retail common key, allowing it to be installed "
|
||||
"on retail consoles or inside of Dolphin")
|
||||
wad_convert_targets.add_argument("-v", "--vwii", action="store_true",
|
||||
help="re-encrypt the WAD with the vWii key, allowing it to theoretically be "
|
||||
"installed from Wii U mode if a Wii U mode WAD installer is created")
|
||||
wad_convert_parser.add_argument("-o", "--output", metavar="OUT", type=str,
|
||||
help="file to output the new WAD to (optional, defaults to '<old_name>_<key>.wad')")
|
||||
# Pack WAD subcommand.
|
||||
wad_pack_parser = wad_subparsers.add_parser("pack", help="pack a directory to a WAD file",
|
||||
description="pack a directory to a WAD file")
|
||||
@ -252,12 +266,6 @@ if __name__ == "__main__":
|
||||
help="Content ID of the content to remove")
|
||||
wad_remove_parser.add_argument("-o", "--output", metavar="OUT", type=str,
|
||||
help="file to output the updated WAD to (optional)")
|
||||
# retail2dev WAD subcommand.
|
||||
wad_r2d_parser = wad_subparsers.add_parser("retail2dev", help="re-encrypt a retail WAD for development consoles",
|
||||
description="re-encrypt a retail WAD for development consoles, and "
|
||||
"update the certs to match; this also fakesigns the WAD")
|
||||
wad_r2d_parser.set_defaults(func=handle_wad_r2d)
|
||||
wad_r2d_parser.add_argument("input", metavar="IN", type=str, help="retail WAD file to re-encrypt")
|
||||
# Set WAD subcommand.
|
||||
wad_set_parser = wad_subparsers.add_parser("set", help="set content in a WAD file",
|
||||
description="replace existing content in a WAD file with new decrypted "
|
||||
@ -284,13 +292,6 @@ if __name__ == "__main__":
|
||||
wad_unpack_parser.add_argument("output", metavar="OUT", type=str, help="output directory")
|
||||
wad_unpack_parser.add_argument("-s", "--skip-hash", help="skips validating the hashes of decrypted "
|
||||
"content", action="store_true")
|
||||
# vwii2wii WAD subcommand.
|
||||
wad_v2w_parser = wad_subparsers.add_parser("vwii2wii", help="re-encrypt a vWii WAD with the common key",
|
||||
description="re-encrypt a vWii WAD with the common key, allowing it to "
|
||||
"be installed in Dolphin and from within Wii mode on Wii U; "
|
||||
"this also fakesigns the WAD")
|
||||
wad_v2w_parser.set_defaults(func=handle_wad_v2w)
|
||||
wad_v2w_parser.add_argument("input", metavar="IN", type=str, help="vWii WAD file to re-encrypt")
|
||||
|
||||
|
||||
# Parse all the args, and call the appropriate function with all of those args if a valid subcommand was passed.
|
||||
|
Loading…
x
Reference in New Issue
Block a user