mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-29 14:54:16 +01: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/nacp.cpp
|
||||||
${source_DIR}/skyline/vfs/npdm.cpp
|
${source_DIR}/skyline/vfs/npdm.cpp
|
||||||
${source_DIR}/skyline/vfs/nca.cpp
|
${source_DIR}/skyline/vfs/nca.cpp
|
||||||
|
${source_DIR}/skyline/vfs/ticket.cpp
|
||||||
${source_DIR}/skyline/services/serviceman.cpp
|
${source_DIR}/skyline/services/serviceman.cpp
|
||||||
${source_DIR}/skyline/services/base_service.cpp
|
${source_DIR}/skyline/services/base_service.cpp
|
||||||
${source_DIR}/skyline/services/common/parcel.cpp
|
${source_DIR}/skyline/services/common/parcel.cpp
|
||||||
|
@ -38,6 +38,11 @@ namespace skyline::crypto {
|
|||||||
titleKeys.emplace(key, valueArray);
|
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) {
|
void KeyStore::PopulateKeys(std::string_view keyName, std::string_view value) {
|
||||||
{
|
{
|
||||||
auto it{key256Names.find(keyName)};
|
auto it{key256Names.find(keyName)};
|
||||||
|
@ -53,5 +53,10 @@ namespace skyline::crypto {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return it->second;
|
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/)
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
#include <kernel/types/KProcess.h>
|
#include <kernel/types/KProcess.h>
|
||||||
|
#include <vfs/ticket.h>
|
||||||
#include "nca.h"
|
#include "nca.h"
|
||||||
#include "nsp.h"
|
#include "nsp.h"
|
||||||
|
|
||||||
namespace skyline::loader {
|
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)) {
|
static void ExtractTickets(const std::shared_ptr<vfs::PartitionFileSystem>& dir, const std::shared_ptr<crypto::KeyStore> &keyStore) {
|
||||||
auto root{nsp->OpenDirectory("", {false, true})};
|
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()) {
|
for (const auto &entry : root->Read()) {
|
||||||
if (entry.name.substr(entry.name.find_last_of('.') + 1) != "nca")
|
if (entry.name.substr(entry.name.find_last_of('.') + 1) != "nca")
|
||||||
continue;
|
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