diff --git a/src/libWiiPy/content.py b/src/libWiiPy/content.py index 96dbce2..ebd55dc 100644 --- a/src/libWiiPy/content.py +++ b/src/libWiiPy/content.py @@ -14,7 +14,7 @@ from .crypto import decrypt_content class ContentRegion: """Creates a ContentRegion object to parse the continuous content region of a WAD. - Attributes: + Parameters ---------- content_region : bytes A bytes object containing the content region of a WAD file. diff --git a/src/libWiiPy/crypto.py b/src/libWiiPy/crypto.py index 2a6d538..e5f198a 100644 --- a/src/libWiiPy/crypto.py +++ b/src/libWiiPy/crypto.py @@ -4,7 +4,6 @@ import struct from .commonkeys import get_common_key from Crypto.Cipher import AES -from Crypto.Util.Padding import pad, unpad def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes: diff --git a/src/libWiiPy/ticket.py b/src/libWiiPy/ticket.py index ee9f11b..3682d09 100644 --- a/src/libWiiPy/ticket.py +++ b/src/libWiiPy/ticket.py @@ -13,7 +13,7 @@ from typing import List class TitleLimit: """Creates a TitleLimit object that contains the type of restriction and the limit. - Attributes: + Attributes ---------- limit_type : int The type of play limit applied. @@ -31,12 +31,28 @@ class TitleLimit: class Ticket: """Creates a Ticket object to parse a Ticket file to retrieve the Title Key needed to decrypt it. - Attributes: + Parameters ---------- ticket : bytes A bytes object containing the contents of a ticket file. - """ + Attributes + ---------- + signature : bytes + The signature applied to the ticket. + ticket_version : int + The version of the ticket. + title_key_enc : bytes + The Title Key contained in the ticket, in encrypted form. + ticket_id : bytes + The unique ID of this ticket, used for console-specific title installations. + console_id : int + The unique ID of the console this ticket was designed for, if this is a console-specific ticket. + title_version : int + The version of the title this ticket was designed for. + common_key_index : int + The index of the common key required to decrypt this ticket's Title Key. + """ def __init__(self, ticket): self.ticket = ticket # Signature blob header @@ -45,7 +61,7 @@ class Ticket: # v0 ticket data self.signature_issuer: str # Who issued the signature for the ticket self.ecdh_data: bytes # Involved in created one-time keys for console-specific title installs. - self.ticket_version: int # The version of the ticket format. + self.ticket_version: int # The version of the current ticket file. self.title_key_enc: bytes # The title key of the ticket's respective title, encrypted by a common key. self.ticket_id: bytes # Used as the IV when decrypting the title key for console-specific title installs. self.console_id: int # ID of the console that the ticket was issued for. @@ -118,56 +134,6 @@ class Ticket: limit_value = int.from_bytes(ticket_data.read(4)) self.title_limits_list.append(TitleLimit(limit_type, limit_value)) - def get_signature(self): - """Gets the signature of the ticket. - - Returns - ------- - bytes - The signature. - """ - return self.signature - - def get_ticket_version(self): - """Gets the version of the ticket. - - Returns - ------- - int - The version. - """ - return self.ticket_version - - def get_title_key_enc(self): - """Gets the Title Key contained in the ticket, in encrypted form. - - Returns - ------- - bytes - The encrypted Title Key. - """ - return self.title_key_enc - - def get_ticket_id(self): - """Gets the ID of the ticket. - - Returns - ------- - bytes - The ID of the ticket. - """ - return self.ticket_id - - def get_console_id(self): - """Gets the ID of the console this ticket is designed for, if the ticket is console-specific. - - Returns - ------- - bytes - The ID of the console. - """ - return self.console_id - def get_title_id(self): """Gets the Title ID of the ticket's associated title. @@ -179,30 +145,6 @@ class Ticket: title_id_str = str(self.title_id.decode()) return title_id_str - def get_title_version(self): - """Gets the version of the ticket's associated title that this ticket is designed for. - - Returns - ------- - int - The version of the title. - """ - return self.title_version - - def get_common_key_index(self): - """Gets the index of the common key used to encrypt the Title Key contained in the ticket. - - Returns - ------- - int - The index of the common key required. - - See Also - -------- - commonkeys.get_common_key - """ - return self.common_key_index - def get_common_key_type(self): """Gets the name of the common key used to encrypt the Title Key contained in the ticket. @@ -233,4 +175,3 @@ class Ticket: """ title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id) return title_key - diff --git a/src/libWiiPy/tmd.py b/src/libWiiPy/tmd.py index f0ed6e3..a033706 100644 --- a/src/libWiiPy/tmd.py +++ b/src/libWiiPy/tmd.py @@ -14,17 +14,32 @@ class TMD: """ Creates a TMD object to parse a TMD file to retrieve information about a title. - Attributes: + Parameters ---------- tmd : bytes A bytes object containing the contents of a TMD file. + + Attributes + ---------- + title_id : str + The title ID of the title listed in the TMD. + title_version : int + The version of the title listed in the TMD. + tmd_version : int + The version of the TMD. + ios_tid : str + The title ID of the IOS the title runs on. + ios_version : int + The IOS version the title runs on. + num_contents : int + The number of contents listed in the TMD. """ def __init__(self, tmd): self.tmd = tmd self.sig_type: int self.sig: bytearray self.issuer: bytearray # Follows the format "Root-CA%08x-CP%08x" - self.version: int # This seems to always be 0 no matter what? + self.tmd_version: int # This seems to always be 0 no matter what? self.ca_crl_version: int self.signer_crl_version: int self.vwii: int # Whether the title is for the vWii. 0 = No, 1 = Yes @@ -50,7 +65,7 @@ class TMD: self.issuer = tmd_data.read(64) # TMD version, seems to usually be 0, but I've seen references to other numbers tmd_data.seek(0x180) - self.version = int.from_bytes(tmd_data.read(1)) + self.tmd_version = int.from_bytes(tmd_data.read(1)) # TODO: label tmd_data.seek(0x181) self.ca_crl_version = tmd_data.read(1) @@ -111,26 +126,6 @@ class TMD: int(content_record_hdr[2]), int.from_bytes(content_record_hdr[3]), binascii.hexlify(content_record_hdr[4]))) - def get_title_id(self): - """Gets the TID of the TMD's associated title. - - Returns - ------- - str - The Title ID. - """ - return self.title_id - - def get_title_version(self): - """Gets the version of the TMD's associated title. - - Returns - ------- - int - The version of the title. - """ - return self.title_version - def get_title_region(self): """Gets the region of the TMD's associated title. @@ -167,36 +162,6 @@ class TMD: else: return False - def get_tmd_version(self): - """Gets the version of the TMD. - - Returns - ------- - int - The version of the TMD. - """ - return self.version - - def get_required_ios_tid(self): - """Gets the TID of the required IOS for the title. - - Returns - ------- - str - The Title ID of the required IOS version. - """ - return self.ios_tid - - def get_required_ios(self): - """Gets the required IOS version for the title. - - Returns - ------- - int - The required IOS version. - """ - return self.ios_version - def get_title_type(self): """Gets the type of the TMD's associated title. @@ -252,16 +217,6 @@ class TMD: case _: return "Unknown" - def get_num_contents(self): - """Gets the number of contents listed in the TMD. - - Returns - ------- - int - The number of contents. - """ - return self.num_contents - def get_content_record(self, record): """Gets the content record at the specified index. diff --git a/src/libWiiPy/types.py b/src/libWiiPy/types.py index da78e14..fc0a57e 100644 --- a/src/libWiiPy/types.py +++ b/src/libWiiPy/types.py @@ -9,7 +9,7 @@ class ContentRecord: """ Creates a content record object that contains the details of a content contained in a title. - Attributes: + Attributes ---------- content_id : int ID of the content. diff --git a/src/libWiiPy/wad.py b/src/libWiiPy/wad.py index 37516c7..2fe3de3 100644 --- a/src/libWiiPy/wad.py +++ b/src/libWiiPy/wad.py @@ -11,7 +11,7 @@ class WAD: """ Creates a WAD object to parse the header of a WAD file and retrieve the data contained in it. - Attributes: + Parameters ---------- wad : bytes A bytes object containing the contents of a WAD file. @@ -76,7 +76,7 @@ class WAD: self.wad_tik_offset = int(64 * round((self.wad_crl_offset + self.wad_crl_size) / 64)) self.wad_tmd_offset = int(64 * round((self.wad_tik_offset + self.wad_tik_size) / 64)) self.wad_content_offset = int(64 * round((self.wad_tmd_offset + self.wad_tmd_size) / 64)) - # meta is also never used, but Nintendo's tools calculate it so we should too. + # meta is also never used, but Nintendo's tools calculate it, so we should too. self.wad_meta_offset = int(64 * round((self.wad_content_offset + self.wad_content_size) / 64)) def get_cert_region(self): @@ -137,7 +137,19 @@ class WAD: int The size of the content data in the WAD. """ - return self.wad_content_offset, self.wad_tmd_size + return self.wad_content_offset, self.wad_content_size + + def get_meta_region(self): + """Gets the offset and size of the meta region of the WAD, which is typically unused. + + Returns + ------- + int + The offset of the meta region in the WAD. + int + The size of the meta region in the WAD. + """ + return self.wad_meta_offset, self.wad_meta_size def get_wad_type(self): """Gets the type of the WAD. @@ -157,9 +169,9 @@ class WAD: bytes The certificate data. """ - waddata = io.BytesIO(self.wad) - waddata.seek(self.wad_cert_offset) - cert_data = waddata.read(self.wad_cert_size) + wad_data = io.BytesIO(self.wad) + wad_data.seek(self.wad_cert_offset) + cert_data = wad_data.read(self.wad_cert_size) return cert_data def get_crl_data(self): @@ -170,9 +182,9 @@ class WAD: bytes The crl data. """ - waddata = io.BytesIO(self.wad) - waddata.seek(self.wad_crl_offset) - crl_data = waddata.read(self.wad_crl_size) + wad_data = io.BytesIO(self.wad) + wad_data.seek(self.wad_crl_offset) + crl_data = wad_data.read(self.wad_crl_size) return crl_data def get_ticket_data(self): @@ -183,9 +195,9 @@ class WAD: bytes The ticket data. """ - waddata = io.BytesIO(self.wad) - waddata.seek(self.wad_tik_offset) - ticket_data = waddata.read(self.wad_tik_size) + wad_data = io.BytesIO(self.wad) + wad_data.seek(self.wad_tik_offset) + ticket_data = wad_data.read(self.wad_tik_size) return ticket_data def get_tmd_data(self): @@ -196,9 +208,9 @@ class WAD: bytes The TMD data. """ - waddata = io.BytesIO(self.wad) - waddata.seek(self.wad_tmd_offset) - tmd_data = waddata.read(self.wad_tmd_size) + wad_data = io.BytesIO(self.wad) + wad_data.seek(self.wad_tmd_offset) + tmd_data = wad_data.read(self.wad_tmd_size) return tmd_data def get_content_data(self): @@ -209,7 +221,20 @@ class WAD: bytes The content data. """ - waddata = io.BytesIO(self.wad) - waddata.seek(self.wad_content_offset) - content_data = waddata.read(self.wad_content_size) + wad_data = io.BytesIO(self.wad) + wad_data.seek(self.wad_content_offset) + content_data = wad_data.read(self.wad_content_size) return content_data + + def get_meta_data(self): + """Gets the meta region of the WAD, which is typically unused. + + Returns + ------- + bytes + The meta region. + """ + wad_data = io.BytesIO(self.wad) + wad_data.seek(self.wad_meta_offset) + meta_data = wad_data.read(self.wad_meta_size) + return meta_data