mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-27 15:35:29 +03:00
Add NSP ticket extraction support
This commit is contained in:
parent
77d8d1bee1
commit
75b769ca1d
@ -82,6 +82,7 @@ add_library(skyline SHARED
|
||||
${source_DIR}/skyline/vfs/nacp.cpp
|
||||
${source_DIR}/skyline/vfs/npdm.cpp
|
||||
${source_DIR}/skyline/vfs/nca.cpp
|
||||
${source_DIR}/skyline/vfs/ticket.cpp
|
||||
${source_DIR}/skyline/services/serviceman.cpp
|
||||
${source_DIR}/skyline/services/base_service.cpp
|
||||
${source_DIR}/skyline/services/common/parcel.cpp
|
||||
|
@ -38,6 +38,11 @@ namespace skyline::crypto {
|
||||
titleKeys.emplace(key, valueArray);
|
||||
}
|
||||
|
||||
void KeyStore::PopulateTitleKey(Key128 keyName, Key128 value) {
|
||||
if (!titleKeys.contains(keyName))
|
||||
titleKeys.emplace(keyName, value);
|
||||
}
|
||||
|
||||
void KeyStore::PopulateKeys(std::string_view keyName, std::string_view value) {
|
||||
{
|
||||
auto it{key256Names.find(keyName)};
|
||||
|
@ -53,5 +53,10 @@ namespace skyline::crypto {
|
||||
return std::nullopt;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note Any title keys which are already in the store will not have their values updated
|
||||
*/
|
||||
void PopulateTitleKey(Key128 keyName, Key128 value);
|
||||
};
|
||||
}
|
||||
|
@ -2,13 +2,30 @@
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include <vfs/ticket.h>
|
||||
#include "nca.h"
|
||||
#include "nsp.h"
|
||||
|
||||
namespace skyline::loader {
|
||||
NspLoader::NspLoader(const std::shared_ptr<vfs::Backing> &backing, const std::shared_ptr<crypto::KeyStore> &keyStore) : nsp(std::make_shared<vfs::PartitionFileSystem>(backing)) {
|
||||
auto root{nsp->OpenDirectory("", {false, true})};
|
||||
static void ExtractTickets(const std::shared_ptr<vfs::PartitionFileSystem>& dir, const std::shared_ptr<crypto::KeyStore> &keyStore) {
|
||||
std::vector<vfs::Ticket> tickets;
|
||||
|
||||
auto dirContent{dir->OpenDirectory("", {false, true})};
|
||||
for (const auto &entry : dirContent->Read()) {
|
||||
if (entry.name.substr(entry.name.find_last_of('.') + 1) == "tik")
|
||||
tickets.emplace_back(dir->OpenFile(entry.name));
|
||||
}
|
||||
|
||||
for (auto ticket : tickets) {
|
||||
auto titleKey{span(ticket.titleKeyBlock).subspan(0, 16).as<crypto::KeyStore::Key128>()};
|
||||
keyStore->PopulateTitleKey(ticket.rightsId, titleKey);
|
||||
}
|
||||
}
|
||||
|
||||
NspLoader::NspLoader(const std::shared_ptr<vfs::Backing> &backing, const std::shared_ptr<crypto::KeyStore> &keyStore) : nsp(std::make_shared<vfs::PartitionFileSystem>(backing)) {
|
||||
ExtractTickets(nsp, keyStore);
|
||||
|
||||
auto root{nsp->OpenDirectory("", {false, true})};
|
||||
for (const auto &entry : root->Read()) {
|
||||
if (entry.name.substr(entry.name.find_last_of('.') + 1) != "nca")
|
||||
continue;
|
||||
|
42
app/src/main/cpp/skyline/vfs/ticket.cpp
Normal file
42
app/src/main/cpp/skyline/vfs/ticket.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "ticket.h"
|
||||
|
||||
namespace skyline::vfs {
|
||||
/**
|
||||
* @url https://switchbrew.org/wiki/Ticket#Signature_type
|
||||
*/
|
||||
enum class SignatureType : u32 {
|
||||
Rsa4096Sha1 = 0x010000,
|
||||
Rsa2048Sha1 = 0x010001,
|
||||
EcdsaSha1 = 0x010002,
|
||||
Rsa4096Sha256 = 0x010003,
|
||||
Rsa2048Sha256 = 0x010004,
|
||||
EcdsaSha256 = 0x010005,
|
||||
};
|
||||
|
||||
Ticket::Ticket(const std::shared_ptr<vfs::Backing> &backing) {
|
||||
auto type{backing->Read<SignatureType>()};
|
||||
|
||||
size_t offset;
|
||||
switch (type) {
|
||||
case SignatureType::Rsa4096Sha1:
|
||||
case SignatureType::Rsa4096Sha256:
|
||||
offset = 0x240;
|
||||
break;
|
||||
case SignatureType::Rsa2048Sha1:
|
||||
case SignatureType::Rsa2048Sha256:
|
||||
offset = 0x140;
|
||||
break;
|
||||
case SignatureType::EcdsaSha1:
|
||||
case SignatureType::EcdsaSha256:
|
||||
offset = 0x80;
|
||||
break;
|
||||
default:
|
||||
throw exception("Could not find valid signature type 0x{:X}", type);
|
||||
}
|
||||
|
||||
*this = backing->Read<Ticket>(offset);
|
||||
}
|
||||
}
|
38
app/src/main/cpp/skyline/vfs/ticket.h
Normal file
38
app/src/main/cpp/skyline/vfs/ticket.h
Normal file
@ -0,0 +1,38 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vfs/backing.h>
|
||||
#include <crypto/key_store.h>
|
||||
|
||||
namespace skyline::vfs {
|
||||
/**
|
||||
* @brief The Ticket struct allows easy access to ticket files, a format used to store an encrypted title keys
|
||||
* @url https://switchbrew.org/wiki/Ticket
|
||||
*/
|
||||
struct Ticket {
|
||||
enum class TitleKeyType : u8 {
|
||||
Common = 0x0, //!< The title key is stored as a 16-byte block
|
||||
Personal = 0x1, //!< The title key is stored as a personalized RSA-2048 message
|
||||
};
|
||||
|
||||
std::array<u8, 0x40> issuer;
|
||||
std::array<u8, 0x100> titleKeyBlock;
|
||||
u8 _pad0_[0x1];
|
||||
TitleKeyType titleKeyType;
|
||||
u8 _pad1_[0x3];
|
||||
u8 masterKeyRevision;
|
||||
u8 _pad2_[0xA];
|
||||
u64 ticketId;
|
||||
u64 deviceId;
|
||||
crypto::KeyStore::Key128 rightsId;
|
||||
u32 accountId;
|
||||
u8 _pad3_[0xC];
|
||||
|
||||
Ticket() = default;
|
||||
|
||||
Ticket(const std::shared_ptr<vfs::Backing> &backing);
|
||||
};
|
||||
static_assert(sizeof(Ticket) == 0x180);
|
||||
}
|
Loading…
Reference in New Issue
Block a user