mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-27 22:01:01 -04:00
Handle cert chain data in a title as a CertificateChain instead of bytes
This commit is contained in:
parent
ece19177c4
commit
8a15b1e82e
@ -40,10 +40,10 @@ def download_title(title_id: str, title_version: int = None, wiiu_endpoint: bool
|
|||||||
"""
|
"""
|
||||||
# First, create the new title.
|
# First, create the new title.
|
||||||
title = Title()
|
title = Title()
|
||||||
# Download and load the TMD, Ticket, and certs.
|
# Download and load the certificate chain, TMD, and Ticket.
|
||||||
|
title.load_cert_chain(download_cert_chain(wiiu_endpoint, endpoint_override))
|
||||||
title.load_tmd(download_tmd(title_id, title_version, wiiu_endpoint, endpoint_override))
|
title.load_tmd(download_tmd(title_id, title_version, wiiu_endpoint, endpoint_override))
|
||||||
title.load_ticket(download_ticket(title_id, wiiu_endpoint, endpoint_override))
|
title.load_ticket(download_ticket(title_id, wiiu_endpoint, endpoint_override))
|
||||||
title.wad.set_cert_data(download_cert(wiiu_endpoint, endpoint_override))
|
|
||||||
# Download all contents
|
# Download all contents
|
||||||
title.load_content_records()
|
title.load_content_records()
|
||||||
title.content.content_list = download_contents(title_id, title.tmd, wiiu_endpoint, endpoint_override)
|
title.content.content_list = download_contents(title_id, title.tmd, wiiu_endpoint, endpoint_override)
|
||||||
@ -146,9 +146,9 @@ def download_ticket(title_id: str, wiiu_endpoint: bool = False, endpoint_overrid
|
|||||||
return ticket
|
return ticket
|
||||||
|
|
||||||
|
|
||||||
def download_cert(wiiu_endpoint: bool = False, endpoint_override: str = None) -> bytes:
|
def download_cert_chain(wiiu_endpoint: bool = False, endpoint_override: str = None) -> bytes:
|
||||||
"""
|
"""
|
||||||
Downloads the signing certificate used by all WADs. This uses System Menu 4.3U as the source.
|
Downloads the signing certificate chain used by all WADs. This uses System Menu 4.3U as the source.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
@ -163,7 +163,7 @@ def download_cert(wiiu_endpoint: bool = False, endpoint_override: str = None) ->
|
|||||||
bytes
|
bytes
|
||||||
The cert file.
|
The cert file.
|
||||||
"""
|
"""
|
||||||
# Download the TMD and cetk for the System Menu 4.3U.
|
# Download the TMD and cetk for System Menu 4.3U (v513).
|
||||||
if endpoint_override is not None:
|
if endpoint_override is not None:
|
||||||
endpoint_url = _validate_endpoint(endpoint_override)
|
endpoint_url = _validate_endpoint(endpoint_override)
|
||||||
else:
|
else:
|
||||||
@ -175,18 +175,18 @@ def download_cert(wiiu_endpoint: bool = False, endpoint_override: str = None) ->
|
|||||||
cetk_url = endpoint_url + "0000000100000002/cetk"
|
cetk_url = endpoint_url + "0000000100000002/cetk"
|
||||||
tmd = requests.get(url=tmd_url, headers={'User-Agent': 'wii libnup/1.0'}, stream=True).content
|
tmd = requests.get(url=tmd_url, headers={'User-Agent': 'wii libnup/1.0'}, stream=True).content
|
||||||
cetk = requests.get(url=cetk_url, headers={'User-Agent': 'wii libnup/1.0'}, stream=True).content
|
cetk = requests.get(url=cetk_url, headers={'User-Agent': 'wii libnup/1.0'}, stream=True).content
|
||||||
# Assemble the certificate.
|
# Assemble the certificate chain.
|
||||||
cert = b''
|
cert_chain = b''
|
||||||
# Certificate Authority data.
|
# Certificate Authority data.
|
||||||
cert += cetk[0x2A4 + 768:]
|
cert_chain += cetk[0x2A4 + 768:]
|
||||||
# Certificate Policy data.
|
# Certificate Policy (TMD certificate) data.
|
||||||
cert += tmd[0x328:0x328 + 768]
|
cert_chain += tmd[0x328:0x328 + 768]
|
||||||
# XS data.
|
# XS (Ticket certificate) data.
|
||||||
cert += cetk[0x2A4:0x2A4 + 768]
|
cert_chain += cetk[0x2A4:0x2A4 + 768]
|
||||||
# Since the cert is always the same, check the hash to make sure nothing went wildly wrong.
|
# Since the cert chain is always the same, check the hash to make sure nothing went wildly wrong.
|
||||||
if hashlib.sha1(cert).hexdigest() != "ace0f15d2a851c383fe4657afc3840d6ffe30ad0":
|
if hashlib.sha1(cert_chain).hexdigest() != "ace0f15d2a851c383fe4657afc3840d6ffe30ad0":
|
||||||
raise Exception("An unknown error has occurred downloading and creating the certificate.")
|
raise Exception("An unknown error has occurred downloading and creating the certificate.")
|
||||||
return cert
|
return cert_chain
|
||||||
|
|
||||||
|
|
||||||
def download_content(title_id: str, content_id: int, wiiu_endpoint: bool = False,
|
def download_content(title_id: str, content_id: int, wiiu_endpoint: bool = False,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
|
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
from .cert import CertificateChain
|
||||||
from .content import ContentRegion
|
from .content import ContentRegion
|
||||||
from .ticket import Ticket
|
from .ticket import Ticket
|
||||||
from .tmd import TMD
|
from .tmd import TMD
|
||||||
@ -21,6 +22,8 @@ class Title:
|
|||||||
----------
|
----------
|
||||||
wad: WAD
|
wad: WAD
|
||||||
A WAD object of a WAD containing the title's data.
|
A WAD object of a WAD containing the title's data.
|
||||||
|
cert_chain: CertificateChain
|
||||||
|
The chain of certificates used to verify the contents of a title.
|
||||||
tmd: TMD
|
tmd: TMD
|
||||||
A TMD object of the title's TMD.
|
A TMD object of the title's TMD.
|
||||||
ticket: Ticket
|
ticket: Ticket
|
||||||
@ -30,6 +33,7 @@ class Title:
|
|||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.wad: WAD = WAD()
|
self.wad: WAD = WAD()
|
||||||
|
self.cert_chain: CertificateChain = CertificateChain()
|
||||||
self.tmd: TMD = TMD()
|
self.tmd: TMD = TMD()
|
||||||
self.ticket: Ticket = Ticket()
|
self.ticket: Ticket = Ticket()
|
||||||
self.content: ContentRegion = ContentRegion()
|
self.content: ContentRegion = ContentRegion()
|
||||||
@ -47,6 +51,9 @@ class Title:
|
|||||||
# Create a new WAD object based on the WAD data provided.
|
# Create a new WAD object based on the WAD data provided.
|
||||||
self.wad = WAD()
|
self.wad = WAD()
|
||||||
self.wad.load(wad)
|
self.wad.load(wad)
|
||||||
|
# Load the certificate chain.
|
||||||
|
self.cert_chain = CertificateChain()
|
||||||
|
self.cert_chain.load(self.wad.get_cert_data())
|
||||||
# Load the TMD.
|
# Load the TMD.
|
||||||
self.tmd = TMD()
|
self.tmd = TMD()
|
||||||
self.tmd.load(self.wad.get_tmd_data())
|
self.tmd.load(self.wad.get_tmd_data())
|
||||||
@ -75,6 +82,8 @@ class Title:
|
|||||||
# Set WAD type to ib if the title being packed is boot2.
|
# Set WAD type to ib if the title being packed is boot2.
|
||||||
if self.tmd.title_id == "0000000100000001":
|
if self.tmd.title_id == "0000000100000001":
|
||||||
self.wad.wad_type = "ib"
|
self.wad.wad_type = "ib"
|
||||||
|
# Dump the certificate chain and set it in the WAD.
|
||||||
|
self.wad.set_cert_data(self.cert_chain.dump())
|
||||||
# Dump the TMD and set it in the WAD.
|
# Dump the TMD and set it in the WAD.
|
||||||
# This requires updating the content records and number of contents in the TMD first.
|
# This requires updating the content records and number of contents in the TMD first.
|
||||||
self.tmd.content_records = self.content.content_records # This may not be needed because it's a ref already
|
self.tmd.content_records = self.content.content_records # This may not be needed because it's a ref already
|
||||||
@ -87,6 +96,19 @@ class Title:
|
|||||||
self.wad.set_content_data(content_data, content_size)
|
self.wad.set_content_data(content_data, content_size)
|
||||||
return self.wad.dump()
|
return self.wad.dump()
|
||||||
|
|
||||||
|
def load_cert_chain(self, cert_chain: bytes) -> None:
|
||||||
|
"""
|
||||||
|
Load an existing certificate chain into the title. Note that this will overwrite any existing certificate chain
|
||||||
|
data for this title.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
cert_chain: bytes
|
||||||
|
The data for the certificate chain to load.
|
||||||
|
"""
|
||||||
|
self.cert_chain.load(cert_chain)
|
||||||
|
|
||||||
|
|
||||||
def load_tmd(self, tmd: bytes) -> None:
|
def load_tmd(self, tmd: bytes) -> None:
|
||||||
"""
|
"""
|
||||||
Load existing TMD data into the title. Note that this will overwrite any existing TMD data for this title.
|
Load existing TMD data into the title. Note that this will overwrite any existing TMD data for this title.
|
||||||
@ -94,9 +116,8 @@ class Title:
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
tmd : bytes
|
tmd : bytes
|
||||||
The data for the WAD you wish to load.
|
The data for the TMD to load.
|
||||||
"""
|
"""
|
||||||
# Load TMD.
|
|
||||||
self.tmd.load(tmd)
|
self.tmd.load(tmd)
|
||||||
|
|
||||||
def load_ticket(self, ticket: bytes) -> None:
|
def load_ticket(self, ticket: bytes) -> None:
|
||||||
@ -107,9 +128,8 @@ class Title:
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
ticket : bytes
|
ticket : bytes
|
||||||
The data for the WAD you wish to load.
|
The data for the Ticket to load.
|
||||||
"""
|
"""
|
||||||
# Load Ticket.
|
|
||||||
self.ticket.load(ticket)
|
self.ticket.load(ticket)
|
||||||
|
|
||||||
def load_content_records(self) -> None:
|
def load_content_records(self) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user