diff --git a/modules/title/ciosbuild.py b/modules/title/ciosbuild.py index b833f9b..8339ef6 100644 --- a/modules/title/ciosbuild.py +++ b/modules/title/ciosbuild.py @@ -123,6 +123,14 @@ def build_cios(args): except ValueError: raise ValueError(f"The provided version \"{args.version}\" is not valid!") + # 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. + 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.tmd.vwii = 0 + # Ensure the WAD is fakesigned. title.fakesign() diff --git a/modules/title/info.py b/modules/title/info.py index 0073c60..8a124ba 100644 --- a/modules/title/info.py +++ b/modules/title/info.py @@ -95,7 +95,7 @@ def _print_ticket_info(ticket: libWiiPy.title.Ticket): key = "vWii" case _: key = "Unknown (Likely Common)" - print(f" Common Key: {key}") + print(f" Decryption Key: {key}") print(f" Title Key (Encrypted): {binascii.hexlify(ticket.title_key_enc).decode()}") print(f" Title Key (Decrypted): {binascii.hexlify(ticket.get_title_key()).decode()}") diff --git a/modules/title/wad.py b/modules/title/wad.py index cc99e86..404f643 100644 --- a/modules/title/wad.py +++ b/modules/title/wad.py @@ -349,3 +349,28 @@ def handle_wad_r2d(args): 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.tmd.vwii = 0 + title.fakesign() + output_path.write_bytes(title.dump_wad()) + print(f"Successfully re-encrypted vWii WAD to regular WAD \"{output_path.name}\"!") diff --git a/wiipy.py b/wiipy.py index 1066f25..792d7c4 100644 --- a/wiipy.py +++ b/wiipy.py @@ -284,6 +284,13 @@ 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.