- added more es commands. - fixed usb install potential hang if the exit command is sent, but the client stops responding (timeout is now 3s). - added multi select to the games menu. - added game dumping. - added switch2switch support by having a switch act as a usb client to transfer games. - replace std::find with std::ranges (in a few places). - fix rounding of icon in progress box being too round. - fix file copy helper in progress box not updating the progress bar.
102 lines
3.6 KiB
C++
102 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <switch.h>
|
|
#include <span>
|
|
#include "ncm.hpp"
|
|
#include "keys.hpp"
|
|
|
|
namespace sphaira::es {
|
|
|
|
enum { TicketModule = 522 };
|
|
|
|
enum : Result {
|
|
// found ticket has missmatching rights_id from it's name.
|
|
Result_InvalidTicketBadRightsId = MAKERESULT(TicketModule, 71),
|
|
Result_InvalidTicketVersion = MAKERESULT(TicketModule, 72),
|
|
Result_InvalidTicketKeyType = MAKERESULT(TicketModule, 73),
|
|
Result_InvalidTicketKeyRevision = MAKERESULT(TicketModule, 74),
|
|
};
|
|
|
|
enum TicketSigantureType {
|
|
TicketSigantureType_RSA_4096_SHA1 = 0x010000,
|
|
TicketSigantureType_RSA_2048_SHA1 = 0x010001,
|
|
TicketSigantureType_ECDSA_SHA1 = 0x010002,
|
|
TicketSigantureType_RSA_4096_SHA256 = 0x010003,
|
|
TicketSigantureType_RSA_2048_SHA256 = 0x010004,
|
|
TicketSigantureType_ECDSA_SHA256 = 0x010005,
|
|
TicketSigantureType_HMAC_SHA1_160 = 0x010006,
|
|
};
|
|
|
|
enum TicketTitleKeyType {
|
|
TicketTitleKeyType_Common = 0,
|
|
TicketTitleKeyType_Personalized = 1,
|
|
};
|
|
|
|
enum TicketPropertiesBitfield {
|
|
TicketPropertiesBitfield_None = 0,
|
|
// temporary ticket, removed on restart
|
|
TicketPropertiesBitfield_Temporary = 1 << 4,
|
|
};
|
|
|
|
struct TicketData {
|
|
u8 issuer[0x40];
|
|
u8 title_key_block[0x100];
|
|
u8 ticket_version1;
|
|
u8 title_key_type;
|
|
u16 ticket_version2;
|
|
u8 license_type;
|
|
u8 master_key_revision;
|
|
u16 properties_bitfield;
|
|
u8 _0x148[0x8];
|
|
u64 ticket_id;
|
|
u64 device_id;
|
|
FsRightsId rights_id;
|
|
u32 account_id;
|
|
u8 _0x174[0xC];
|
|
u8 _0x180[0x140];
|
|
};
|
|
static_assert(sizeof(TicketData) == 0x2C0);
|
|
|
|
struct EticketRsaDeviceKey {
|
|
u8 ctr[AES_128_KEY_SIZE];
|
|
u8 private_exponent[0x100];
|
|
u8 modulus[0x100];
|
|
u32 public_exponent; ///< Stored using big endian byte order. Must match ETICKET_RSA_DEVICE_KEY_PUBLIC_EXPONENT.
|
|
u8 padding[0x14];
|
|
u64 device_id;
|
|
u8 ghash[0x10];
|
|
};
|
|
static_assert(sizeof(EticketRsaDeviceKey) == 0x240);
|
|
|
|
// es functions.
|
|
Result Initialize();
|
|
void Exit();
|
|
Service* GetServiceSession();
|
|
|
|
// todo: find the ipc that gets personalised tickets.
|
|
// todo: if ipc doesn't exist, manually parse es personalised save.
|
|
// todo: add personalised -> common ticket conversion.
|
|
// todo: make the above an option for both dump and install.
|
|
|
|
Result ImportTicket(const void* tik_buf, u64 tik_size, const void* cert_buf, u64 cert_size);
|
|
Result CountCommonTicket(s32* count);
|
|
Result CountPersonalizedTicket(s32* count);
|
|
Result ListCommonTicket(s32 *out_entries_written, FsRightsId* out_ids, s32 count);
|
|
Result ListPersonalizedTicket(s32 *out_entries_written, FsRightsId* out_ids, s32 count);
|
|
Result ListMissingPersonalizedTicket(s32 *out_entries_written, FsRightsId* out_ids, s32 count); // untested
|
|
Result GetCommonTicketSize(u64 *size_out, const FsRightsId* rightsId);
|
|
Result GetCommonTicketData(u64 *size_out, void *tik_data, u64 tik_size, const FsRightsId* rightsId);
|
|
Result GetCommonTicketAndCertificateSize(u64 *tik_size_out, u64 *cert_size_out, const FsRightsId* rightsId); // [4.0.0+]
|
|
Result GetCommonTicketAndCertificateData(u64 *tik_size_out, u64 *cert_size_out, void* tik_buf, u64 tik_size, void* cert_buf, u64 cert_size, const FsRightsId* rightsId); // [4.0.0+]
|
|
|
|
// ticket functions.
|
|
Result GetTicketDataOffset(std::span<const u8> ticket, u64& out);
|
|
Result GetTicketData(std::span<const u8> ticket, es::TicketData* out);
|
|
Result SetTicketData(std::span<u8> ticket, const es::TicketData* in);
|
|
|
|
Result GetTitleKey(keys::KeyEntry& out, const TicketData& data, const keys::Keys& keys);
|
|
Result DecryptTitleKey(keys::KeyEntry& out, u8 key_gen, const keys::Keys& keys);
|
|
Result PatchTicket(std::span<u8> ticket, const keys::Keys& keys);
|
|
|
|
} // namespace sphaira::es
|