mirror of
https://github.com/Dark98/threeSD.git
synced 2026-07-03 08:39:04 +00:00
Add in complete Ticket support from Citra
This commit is contained in:
@@ -4,10 +4,55 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/ncch/cia_common.h"
|
||||
#include "core/ncch/ticket.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
bool Ticket::Load(const std::vector<u8> file_data, std::size_t offset) {
|
||||
std::size_t total_size = static_cast<std::size_t>(file_data.size() - offset);
|
||||
if (total_size < sizeof(u32))
|
||||
return false;
|
||||
|
||||
std::memcpy(&signature_type, &file_data[offset], sizeof(u32));
|
||||
|
||||
// Signature lengths are variable, and the body follows the signature
|
||||
u32 signature_size = GetSignatureSize(signature_type);
|
||||
if (signature_size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The ticket body start position is rounded to the nearest 0x40 after the signature
|
||||
std::size_t body_start = Common::AlignUp(signature_size + sizeof(u32), 0x40);
|
||||
std::size_t body_end = body_start + sizeof(Body);
|
||||
|
||||
if (total_size < body_end)
|
||||
return false;
|
||||
|
||||
// Read signature + ticket body
|
||||
signature.resize(signature_size);
|
||||
memcpy(signature.data(), &file_data[offset + sizeof(u32)], signature_size);
|
||||
memcpy(&body, &file_data[offset + body_start], sizeof(Body));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<u8> Ticket::GetData() const {
|
||||
u32 signature_size = GetSignatureSize(signature_type);
|
||||
ASSERT(signature_size != 0);
|
||||
|
||||
const std::size_t body_start = Common::AlignUp(signature_size + sizeof(u32), 0x40);
|
||||
const std::size_t body_end = body_start + sizeof(Body);
|
||||
|
||||
std::vector<u8> out(body_end);
|
||||
std::memcpy(out.data(), &signature_type, sizeof(signature_type));
|
||||
std::memcpy(out.data() + sizeof(signature_type), signature.data(), signature.size());
|
||||
std::memcpy(out.data() + body_start, &body, sizeof(Body));
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr std::string_view TicketIssuer = "Root-CA00000003-XS0000000c";
|
||||
|
||||
// TODO: Make use of this?
|
||||
@@ -23,17 +68,30 @@ constexpr std::array<u8, 44> TicketContentIndex{
|
||||
Ticket BuildFakeTicket(u64 title_id) {
|
||||
Ticket ticket{};
|
||||
ticket.signature_type = 0x10004; // RSA_2048 SHA256
|
||||
|
||||
std::memset(ticket.signature.data(), 0xFF, ticket.signature.size());
|
||||
std::memcpy(ticket.issuer.data(), TicketIssuer.data(), TicketIssuer.size());
|
||||
std::memset(ticket.ecc_public_key.data(), 0xFF, ticket.ecc_public_key.size());
|
||||
ticket.version = 0x01;
|
||||
std::memset(ticket.title_key.data(), 0xFF, ticket.title_key.size());
|
||||
ticket.title_id = title_id;
|
||||
ticket.common_key_index = 0x00;
|
||||
ticket.audit = 0x01;
|
||||
std::memcpy(ticket.content_index.data(), TicketContentIndex.data(), TicketContentIndex.size());
|
||||
|
||||
auto& body = ticket.body;
|
||||
std::memcpy(body.issuer.data(), TicketIssuer.data(), TicketIssuer.size());
|
||||
std::memset(body.ecc_public_key.data(), 0xFF, body.ecc_public_key.size());
|
||||
body.version = 0x01;
|
||||
std::memset(body.title_key.data(), 0xFF, body.title_key.size());
|
||||
body.title_id = title_id;
|
||||
body.common_key_index = 0x00;
|
||||
body.audit = 0x01;
|
||||
std::memcpy(body.content_index.data(), TicketContentIndex.data(), TicketContentIndex.size());
|
||||
// GodMode9 by default sets all remaining 0x80 bytes to 0xFF, but legit tickets only set 0x20
|
||||
std::memset(ticket.content_index.data() + TicketContentIndex.size(), 0xFF, 0x20);
|
||||
std::memset(body.content_index.data() + TicketContentIndex.size(), 0xFF, 0x20);
|
||||
return ticket;
|
||||
}
|
||||
|
||||
Ticket BuildStandardTicket(u64 title_id, Ticket legit_ticket) {
|
||||
Ticket ticket = BuildFakeTicket(title_id);
|
||||
|
||||
// Put in the title key from the legit ticket
|
||||
ticket.body.title_key.swap(legit_ticket.body.title_key);
|
||||
ticket.body.common_key_index = legit_ticket.body.common_key_index;
|
||||
|
||||
return ticket;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user