Deprecate some methods in favor of using properties directly, this is cleaner

This commit is contained in:
Campbell 2024-03-05 21:04:04 -05:00
parent 817fe1b499
commit 3fd5bfd5df
Signed by: NinjaCheetah
GPG Key ID: B547958AF96ED344
6 changed files with 83 additions and 163 deletions

View File

@ -14,7 +14,7 @@ from .crypto import decrypt_content
class ContentRegion: class ContentRegion:
"""Creates a ContentRegion object to parse the continuous content region of a WAD. """Creates a ContentRegion object to parse the continuous content region of a WAD.
Attributes: Parameters
---------- ----------
content_region : bytes content_region : bytes
A bytes object containing the content region of a WAD file. A bytes object containing the content region of a WAD file.

View File

@ -4,7 +4,6 @@
import struct import struct
from .commonkeys import get_common_key from .commonkeys import get_common_key
from Crypto.Cipher import AES 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: def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes:

View File

@ -13,7 +13,7 @@ from typing import List
class TitleLimit: class TitleLimit:
"""Creates a TitleLimit object that contains the type of restriction and the limit. """Creates a TitleLimit object that contains the type of restriction and the limit.
Attributes: Attributes
---------- ----------
limit_type : int limit_type : int
The type of play limit applied. The type of play limit applied.
@ -31,12 +31,28 @@ class TitleLimit:
class Ticket: class Ticket:
"""Creates a Ticket object to parse a Ticket file to retrieve the Title Key needed to decrypt it. """Creates a Ticket object to parse a Ticket file to retrieve the Title Key needed to decrypt it.
Attributes: Parameters
---------- ----------
ticket : bytes ticket : bytes
A bytes object containing the contents of a ticket file. 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): def __init__(self, ticket):
self.ticket = ticket self.ticket = ticket
# Signature blob header # Signature blob header
@ -45,7 +61,7 @@ class Ticket:
# v0 ticket data # v0 ticket data
self.signature_issuer: str # Who issued the signature for the ticket 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.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.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.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. 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)) limit_value = int.from_bytes(ticket_data.read(4))
self.title_limits_list.append(TitleLimit(limit_type, limit_value)) 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): def get_title_id(self):
"""Gets the Title ID of the ticket's associated title. """Gets the Title ID of the ticket's associated title.
@ -179,30 +145,6 @@ class Ticket:
title_id_str = str(self.title_id.decode()) title_id_str = str(self.title_id.decode())
return title_id_str 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): def get_common_key_type(self):
"""Gets the name of the common key used to encrypt the Title Key contained in the ticket. """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) title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id)
return title_key return title_key

View File

@ -14,17 +14,32 @@ class TMD:
""" """
Creates a TMD object to parse a TMD file to retrieve information about a title. Creates a TMD object to parse a TMD file to retrieve information about a title.
Attributes: Parameters
---------- ----------
tmd : bytes tmd : bytes
A bytes object containing the contents of a TMD file. 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): def __init__(self, tmd):
self.tmd = tmd self.tmd = tmd
self.sig_type: int self.sig_type: int
self.sig: bytearray self.sig: bytearray
self.issuer: bytearray # Follows the format "Root-CA%08x-CP%08x" 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.ca_crl_version: int
self.signer_crl_version: int self.signer_crl_version: int
self.vwii: int # Whether the title is for the vWii. 0 = No, 1 = Yes 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) self.issuer = tmd_data.read(64)
# TMD version, seems to usually be 0, but I've seen references to other numbers # TMD version, seems to usually be 0, but I've seen references to other numbers
tmd_data.seek(0x180) 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 # TODO: label
tmd_data.seek(0x181) tmd_data.seek(0x181)
self.ca_crl_version = tmd_data.read(1) 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]), int(content_record_hdr[2]), int.from_bytes(content_record_hdr[3]),
binascii.hexlify(content_record_hdr[4]))) 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): def get_title_region(self):
"""Gets the region of the TMD's associated title. """Gets the region of the TMD's associated title.
@ -167,36 +162,6 @@ class TMD:
else: else:
return False 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): def get_title_type(self):
"""Gets the type of the TMD's associated title. """Gets the type of the TMD's associated title.
@ -252,16 +217,6 @@ class TMD:
case _: case _:
return "Unknown" 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): def get_content_record(self, record):
"""Gets the content record at the specified index. """Gets the content record at the specified index.

View File

@ -9,7 +9,7 @@ class ContentRecord:
""" """
Creates a content record object that contains the details of a content contained in a title. Creates a content record object that contains the details of a content contained in a title.
Attributes: Attributes
---------- ----------
content_id : int content_id : int
ID of the content. ID of the content.

View File

@ -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. Creates a WAD object to parse the header of a WAD file and retrieve the data contained in it.
Attributes: Parameters
---------- ----------
wad : bytes wad : bytes
A bytes object containing the contents of a WAD file. 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_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_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)) 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)) self.wad_meta_offset = int(64 * round((self.wad_content_offset + self.wad_content_size) / 64))
def get_cert_region(self): def get_cert_region(self):
@ -137,7 +137,19 @@ class WAD:
int int
The size of the content data in the WAD. 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): def get_wad_type(self):
"""Gets the type of the WAD. """Gets the type of the WAD.
@ -157,9 +169,9 @@ class WAD:
bytes bytes
The certificate data. The certificate data.
""" """
waddata = io.BytesIO(self.wad) wad_data = io.BytesIO(self.wad)
waddata.seek(self.wad_cert_offset) wad_data.seek(self.wad_cert_offset)
cert_data = waddata.read(self.wad_cert_size) cert_data = wad_data.read(self.wad_cert_size)
return cert_data return cert_data
def get_crl_data(self): def get_crl_data(self):
@ -170,9 +182,9 @@ class WAD:
bytes bytes
The crl data. The crl data.
""" """
waddata = io.BytesIO(self.wad) wad_data = io.BytesIO(self.wad)
waddata.seek(self.wad_crl_offset) wad_data.seek(self.wad_crl_offset)
crl_data = waddata.read(self.wad_crl_size) crl_data = wad_data.read(self.wad_crl_size)
return crl_data return crl_data
def get_ticket_data(self): def get_ticket_data(self):
@ -183,9 +195,9 @@ class WAD:
bytes bytes
The ticket data. The ticket data.
""" """
waddata = io.BytesIO(self.wad) wad_data = io.BytesIO(self.wad)
waddata.seek(self.wad_tik_offset) wad_data.seek(self.wad_tik_offset)
ticket_data = waddata.read(self.wad_tik_size) ticket_data = wad_data.read(self.wad_tik_size)
return ticket_data return ticket_data
def get_tmd_data(self): def get_tmd_data(self):
@ -196,9 +208,9 @@ class WAD:
bytes bytes
The TMD data. The TMD data.
""" """
waddata = io.BytesIO(self.wad) wad_data = io.BytesIO(self.wad)
waddata.seek(self.wad_tmd_offset) wad_data.seek(self.wad_tmd_offset)
tmd_data = waddata.read(self.wad_tmd_size) tmd_data = wad_data.read(self.wad_tmd_size)
return tmd_data return tmd_data
def get_content_data(self): def get_content_data(self):
@ -209,7 +221,20 @@ class WAD:
bytes bytes
The content data. The content data.
""" """
waddata = io.BytesIO(self.wad) wad_data = io.BytesIO(self.wad)
waddata.seek(self.wad_content_offset) wad_data.seek(self.wad_content_offset)
content_data = waddata.read(self.wad_content_size) content_data = wad_data.read(self.wad_content_size)
return content_data 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