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:
"""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.

View File

@ -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:

View File

@ -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

View File

@ -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.

View File

@ -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.

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.
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