summaryrefslogtreecommitdiffstats
path: root/src/core/crypto/key_manager.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/crypto/key_manager.h104
1 files changed, 93 insertions, 11 deletions
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index 978eec8dc..a41abbdfc 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -5,11 +5,18 @@
#pragma once
#include <array>
+#include <map>
#include <string>
#include <boost/container/flat_map.hpp>
#include <boost/optional.hpp>
#include <fmt/format.h>
#include "common/common_types.h"
+#include "core/crypto/partition_data_manager.h"
+#include "core/file_sys/vfs_types.h"
+
+namespace FileUtil {
+class IOFile;
+}
namespace Loader {
enum class ResultStatus : u16;
@@ -22,13 +29,30 @@ constexpr u64 TICKET_FILE_TITLEKEY_OFFSET = 0x180;
using Key128 = std::array<u8, 0x10>;
using Key256 = std::array<u8, 0x20>;
using SHA256Hash = std::array<u8, 0x20>;
+using TicketRaw = std::array<u8, 0x400>;
static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big.");
-static_assert(sizeof(Key256) == 32, "Key128 must be 128 bytes big.");
+static_assert(sizeof(Key256) == 32, "Key256 must be 256 bytes big.");
+
+template <size_t bit_size, size_t byte_size = (bit_size >> 3)>
+struct RSAKeyPair {
+ std::array<u8, byte_size> encryption_key;
+ std::array<u8, byte_size> decryption_key;
+ std::array<u8, byte_size> modulus;
+ std::array<u8, 4> exponent;
+};
+
+enum class KeyCategory : u8 {
+ Standard,
+ Title,
+ Console,
+};
enum class S256KeyType : u64 {
- Header, //
- SDKeySource, // f1=SDKeyType
+ SDKey, // f1=SDKeyType
+ Header, //
+ SDKeySource, // f1=SDKeyType
+ HeaderSource, //
};
enum class S128KeyType : u64 {
@@ -41,6 +65,14 @@ enum class S128KeyType : u64 {
SDSeed, //
Titlekey, // f1=rights id LSB f2=rights id MSB
Source, // f1=source type, f2= sub id
+ Keyblob, // f1=crypto revision
+ KeyblobMAC, // f1=crypto revision
+ TSEC, //
+ SecureBoot, //
+ BIS, // f1=partition (0-3), f2=type {crypt, tweak}
+ HeaderKek, //
+ SDKek, //
+ RSAKek, //
};
enum class KeyAreaKeyType : u8 {
@@ -50,9 +82,19 @@ enum class KeyAreaKeyType : u8 {
};
enum class SourceKeyType : u8 {
- SDKEK,
- AESKEKGeneration,
- AESKeyGeneration,
+ SDKek, //
+ AESKekGeneration, //
+ AESKeyGeneration, //
+ RSAOaepKekGeneration, //
+ Master, //
+ Keyblob, // f2=crypto revision
+ KeyAreaKey, // f2=KeyAreaKeyType
+ Titlekek, //
+ Package2, //
+ HeaderKek, //
+ KeyblobMAC, //
+ ETicketKek, //
+ ETicketKekek, //
};
enum class SDKeyType : u8 {
@@ -60,6 +102,16 @@ enum class SDKeyType : u8 {
NCA,
};
+enum class BISKeyType : u8 {
+ Crypto,
+ Tweak,
+};
+
+enum class RSAKekType : u8 {
+ Mask0,
+ Seed3,
+};
+
template <typename KeyType>
struct KeyIndex {
KeyType type;
@@ -91,6 +143,8 @@ public:
Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0) const;
Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0) const;
+ Key256 GetBISKey(u8 partition_id) const;
+
void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
@@ -100,23 +154,51 @@ public:
// 8*43 and the private file to exist.
void DeriveSDSeedLazy();
+ bool BaseDeriveNecessary() const;
+ void DeriveBase();
+ void DeriveETicket(PartitionDataManager& data);
+
+ void PopulateFromPartitionData(PartitionDataManager& data);
+
private:
- boost::container::flat_map<KeyIndex<S128KeyType>, Key128> s128_keys;
- boost::container::flat_map<KeyIndex<S256KeyType>, Key256> s256_keys;
+ std::map<KeyIndex<S128KeyType>, Key128> s128_keys;
+ std::map<KeyIndex<S256KeyType>, Key256> s256_keys;
+
+ std::array<std::array<u8, 0xB0>, 0x20> encrypted_keyblobs{};
+ std::array<std::array<u8, 0x90>, 0x20> keyblobs{};
bool dev_mode;
void LoadFromFile(const std::string& filename, bool is_title_keys);
void AttemptLoadKeyFile(const std::string& dir1, const std::string& dir2,
const std::string& filename, bool title);
- template <std::size_t Size>
- void WriteKeyToFile(bool title_key, std::string_view keyname, const std::array<u8, Size>& key);
+ template <size_t Size>
+ void WriteKeyToFile(KeyCategory category, std::string_view keyname,
+ const std::array<u8, Size>& key);
+
+ void DeriveGeneralPurposeKeys(u8 crypto_revision);
+
+ void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
+ void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id;
static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id;
};
Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed);
+Key128 DeriveKeyblobKey(const Key128& sbk, const Key128& tsec, Key128 source);
+Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source);
+Key128 DeriveMasterKey(const std::array<u8, 0x90>& keyblob, const Key128& master_source);
+std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblob,
+ const Key128& key);
+
boost::optional<Key128> DeriveSDSeed();
-Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, const KeyManager& keys);
+Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys);
+
+std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save);
+
+// Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority (offset
+// 0x140-0x144 is zero)
+boost::optional<std::pair<Key128, Key128>> ParseTicket(
+ const TicketRaw& ticket, const RSAKeyPair<2048>& eticket_extended_key);
} // namespace Core::Crypto