diff --git a/stratosphere/boot/source/boot_boot_reason.cpp b/stratosphere/boot/source/boot_boot_reason.cpp
index fdad4f0..d78ef8a 100644
--- a/stratosphere/boot/source/boot_boot_reason.cpp
+++ b/stratosphere/boot/source/boot_boot_reason.cpp
@@ -14,10 +14,11 @@
* along with this program. If not, see .
*/
+#include
+
#include "boot_boot_reason.hpp"
#include "boot_pmic_driver.hpp"
#include "boot_rtc_driver.hpp"
-#include "boot_spl_utils.hpp"
namespace sts::boot {
diff --git a/stratosphere/boot/source/boot_display.cpp b/stratosphere/boot/source/boot_display.cpp
index eb3994f..45bd128 100644
--- a/stratosphere/boot/source/boot_display.cpp
+++ b/stratosphere/boot/source/boot_display.cpp
@@ -15,11 +15,11 @@
*/
#include
+#include
#include "boot_display.hpp"
#include "boot_i2c_utils.hpp"
#include "boot_pmc_wrapper.hpp"
-#include "boot_spl_utils.hpp"
#include "boot_registers_clkrst.hpp"
#include "boot_registers_di.hpp"
diff --git a/stratosphere/boot/source/boot_fan_enable.cpp b/stratosphere/boot/source/boot_fan_enable.cpp
index 190c0b6..d235cc5 100644
--- a/stratosphere/boot/source/boot_fan_enable.cpp
+++ b/stratosphere/boot/source/boot_fan_enable.cpp
@@ -14,8 +14,9 @@
* along with this program. If not, see .
*/
+#include
+
#include "boot_fan_enable.hpp"
-#include "boot_spl_utils.hpp"
#include "gpio/gpio_utils.hpp"
diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp
index a28b72a..f7b120c 100644
--- a/stratosphere/boot/source/boot_main.cpp
+++ b/stratosphere/boot/source/boot_main.cpp
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include "boot_boot_reason.hpp"
#include "boot_change_voltage.hpp"
@@ -37,7 +38,6 @@
#include "pinmux/pinmux_initial_configuration.hpp"
#include "boot_power_utils.hpp"
-#include "boot_spl_utils.hpp"
using namespace sts;
diff --git a/stratosphere/boot/source/boot_repair_boot_images.cpp b/stratosphere/boot/source/boot_repair_boot_images.cpp
index 78fd8fa..e2ae290 100644
--- a/stratosphere/boot/source/boot_repair_boot_images.cpp
+++ b/stratosphere/boot/source/boot_repair_boot_images.cpp
@@ -14,9 +14,10 @@
* along with this program. If not, see .
*/
+#include
+
#include "boot_power_utils.hpp"
#include "boot_repair_boot_images.hpp"
-#include "boot_spl_utils.hpp"
#include "updater/updater_api.hpp"
diff --git a/stratosphere/boot/source/boot_spl_utils.cpp b/stratosphere/boot/source/boot_spl_utils.cpp
deleted file mode 100644
index d5e60e1..0000000
--- a/stratosphere/boot/source/boot_spl_utils.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "boot_spl_utils.hpp"
-
-namespace sts::spl {
-
- spl::HardwareType GetHardwareType() {
- u64 out_val = 0;
- R_ASSERT(splGetConfig(SplConfigItem_HardwareType, &out_val));
- return static_cast(out_val);
- }
-
- bool IsRecoveryBoot() {
- u64 val = 0;
- R_ASSERT(splGetConfig(SplConfigItem_IsRecoveryBoot, &val));
- return val != 0;
- }
-
- bool IsMariko() {
- const auto hw_type = GetHardwareType();
- switch (hw_type) {
- case spl::HardwareType::Icosa:
- case spl::HardwareType::Copper:
- return false;
- case spl::HardwareType::Hoag:
- case spl::HardwareType::Iowa:
- return true;
- default:
- std::abort();
- }
- }
-
-}
diff --git a/stratosphere/boot/source/boot_spl_utils.hpp b/stratosphere/boot/source/boot_spl_utils.hpp
deleted file mode 100644
index a12171f..0000000
--- a/stratosphere/boot/source/boot_spl_utils.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-#include
-#include
-
-namespace sts::spl {
-
- enum class HardwareType {
- Icosa = 0,
- Copper = 1,
- Hoag = 2,
- Iowa = 3,
- };
-
- /* SPL Utilities. */
- HardwareType GetHardwareType();
- bool IsRecoveryBoot();
- bool IsMariko();
-
-}
\ No newline at end of file
diff --git a/stratosphere/boot/source/boot_wake_pins.cpp b/stratosphere/boot/source/boot_wake_pins.cpp
index 9df434f..c32c2d1 100644
--- a/stratosphere/boot/source/boot_wake_pins.cpp
+++ b/stratosphere/boot/source/boot_wake_pins.cpp
@@ -14,8 +14,9 @@
* along with this program. If not, see .
*/
+#include
+
#include "boot_pmc_wrapper.hpp"
-#include "boot_spl_utils.hpp"
#include "boot_wake_pins.hpp"
#include "boot_registers_pmc.hpp"
diff --git a/stratosphere/boot/source/gpio/gpio_initial_configuration.cpp b/stratosphere/boot/source/gpio/gpio_initial_configuration.cpp
index c516be8..d16e580 100644
--- a/stratosphere/boot/source/gpio/gpio_initial_configuration.cpp
+++ b/stratosphere/boot/source/gpio/gpio_initial_configuration.cpp
@@ -14,12 +14,11 @@
* along with this program. If not, see .
*/
+#include
+
#include "gpio_initial_configuration.hpp"
#include "gpio_utils.hpp"
-/* TODO: Better way? */
-#include "../boot_spl_utils.hpp"
-
namespace sts::gpio {
namespace {
diff --git a/stratosphere/boot/source/pinmux/pinmux_initial_configuration.cpp b/stratosphere/boot/source/pinmux/pinmux_initial_configuration.cpp
index 091c55f..5076932 100644
--- a/stratosphere/boot/source/pinmux/pinmux_initial_configuration.cpp
+++ b/stratosphere/boot/source/pinmux/pinmux_initial_configuration.cpp
@@ -14,13 +14,11 @@
* along with this program. If not, see .
*/
+#include
#include "pinmux_initial_configuration.hpp"
#include "pinmux_utils.hpp"
-/* TODO: Better way? */
-#include "../boot_spl_utils.hpp"
-
namespace sts::pinmux {
namespace {
diff --git a/stratosphere/boot/source/updater/updater_api.hpp b/stratosphere/boot/source/updater/updater_api.hpp
index fcca1da..1baa7e9 100644
--- a/stratosphere/boot/source/updater/updater_api.hpp
+++ b/stratosphere/boot/source/updater/updater_api.hpp
@@ -17,6 +17,7 @@
#pragma once
#include
#include
+#include
#include "updater_types.hpp"
diff --git a/stratosphere/boot/source/updater/updater_types.hpp b/stratosphere/boot/source/updater/updater_types.hpp
index 5c3f9c0..6abd7cd 100644
--- a/stratosphere/boot/source/updater/updater_types.hpp
+++ b/stratosphere/boot/source/updater/updater_types.hpp
@@ -18,9 +18,6 @@
#include
#include
-/* TODO: Better way to do this? */
-#include "../boot_spl_utils.hpp"
-
namespace sts::updater {
/* Types. */
diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere
index 13e3f51..ca344e1 160000
--- a/stratosphere/libstratosphere
+++ b/stratosphere/libstratosphere
@@ -1 +1 @@
-Subproject commit 13e3f517cb5db1053e01fb21ec189728d5b9d6db
+Subproject commit ca344e1d19267779a59b6a212683792538bb76af
diff --git a/stratosphere/spl/source/spl_api.cpp b/stratosphere/spl/source/spl_api.cpp
deleted file mode 100644
index b43ecca..0000000
--- a/stratosphere/spl/source/spl_api.cpp
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-
-#include "spl_api.hpp"
-#include "spl_smc.hpp"
-
-#include "spl_ctr_drbg.hpp"
-
-namespace sts::spl {
-
- namespace {
-
- /* Convenient defines. */
- constexpr size_t DeviceAddressSpaceAlignSize = 0x400000;
- constexpr size_t DeviceAddressSpaceAlignMask = DeviceAddressSpaceAlignSize - 1;
- constexpr u32 WorkBufferMapBase = 0x80000000u;
- constexpr u32 CryptAesInMapBase = 0x90000000u;
- constexpr u32 CryptAesOutMapBase = 0xC0000000u;
- constexpr size_t CryptAesSizeMax = static_cast(CryptAesOutMapBase - CryptAesInMapBase);
-
- constexpr size_t RsaPrivateKeySize = 0x100;
- constexpr size_t RsaPrivateKeyMetaSize = 0x30;
- constexpr size_t LabelDigestSizeMax = 0x20;
-
- constexpr size_t WorkBufferSizeMax = 0x800;
-
- constexpr size_t MaxAesKeyslots = 6;
- constexpr size_t MaxAesKeyslotsDeprecated = 4;
-
- /* Max Keyslots helper. */
- inline size_t GetMaxKeyslots() {
- return (GetRuntimeFirmwareVersion() >= FirmwareVersion_600) ? MaxAesKeyslots : MaxAesKeyslotsDeprecated;
- }
-
- /* Type definitions. */
- class ScopedAesKeyslot {
- private:
- u32 slot;
- bool has_slot;
- public:
- ScopedAesKeyslot() : slot(0), has_slot(false) {
- /* ... */
- }
- ~ScopedAesKeyslot() {
- if (has_slot) {
- spl::FreeAesKeyslot(slot, this);
- }
- }
-
- u32 GetKeyslot() const {
- return this->slot;
- }
-
- Result Allocate() {
- R_TRY(spl::AllocateAesKeyslot(&this->slot, this));
- this->has_slot = true;
- return ResultSuccess;
- }
- };
-
- struct SeLinkedListEntry {
- u32 num_entries;
- u32 address;
- u32 size;
- };
-
- struct SeCryptContext {
- SeLinkedListEntry in;
- SeLinkedListEntry out;
- };
-
- class DeviceAddressSpaceMapHelper {
- private:
- Handle das_hnd;
- u64 dst_addr;
- u64 src_addr;
- size_t size;
- u32 perm;
- public:
- DeviceAddressSpaceMapHelper(Handle h, u64 dst, u64 src, size_t sz, u32 p) : das_hnd(h), dst_addr(dst), src_addr(src), size(sz), perm(p) {
- R_ASSERT(svcMapDeviceAddressSpaceAligned(this->das_hnd, CUR_PROCESS_HANDLE, this->src_addr, this->size, this->dst_addr, this->perm));
- }
- ~DeviceAddressSpaceMapHelper() {
- R_ASSERT(svcUnmapDeviceAddressSpace(this->das_hnd, CUR_PROCESS_HANDLE, this->src_addr, this->size, this->dst_addr));
- }
- };
-
- /* Global variables. */
- CtrDrbg g_drbg;
- Event g_se_event;
- IEvent *g_se_keyslot_available_event;
-
- Handle g_se_das_hnd;
- u32 g_se_mapped_work_buffer_addr;
- u8 __attribute__((aligned(0x1000))) g_work_buffer[2 * WorkBufferSizeMax];
-
- HosMutex g_async_op_lock;
-
- const void *g_keyslot_owners[MaxAesKeyslots];
- BootReasonValue g_boot_reason;
- bool g_boot_reason_set;
-
- /* Boot Reason accessors. */
- BootReasonValue GetBootReason() {
- return g_boot_reason;
- }
-
- bool IsBootReasonSet() {
- return g_boot_reason_set;
- }
-
- /* Initialization functionality. */
- void InitializeCtrDrbg() {
- u8 seed[CtrDrbg::SeedSize];
-
- if (smc::GenerateRandomBytes(seed, sizeof(seed)) != smc::Result::Success) {
- std::abort();
- }
-
- g_drbg.Initialize(seed);
- }
-
- void InitializeSeEvents() {
- u64 irq_num;
- smc::GetConfig(&irq_num, 1, SplConfigItem_SecurityEngineIrqNumber);
- Handle hnd;
- R_ASSERT(svcCreateInterruptEvent(&hnd, irq_num, 1));
- eventLoadRemote(&g_se_event, hnd, true);
-
- g_se_keyslot_available_event = CreateWriteOnlySystemEvent();
- g_se_keyslot_available_event->Signal();
- }
-
- void InitializeDeviceAddressSpace() {
- constexpr u64 DeviceName_SE = 29;
-
- /* Create Address Space. */
- R_ASSERT(svcCreateDeviceAddressSpace(&g_se_das_hnd, 0, (1ul << 32)));
-
- /* Attach it to the SE. */
- R_ASSERT(svcAttachDeviceAddressSpace(DeviceName_SE, g_se_das_hnd));
-
- const u64 work_buffer_addr = reinterpret_cast(g_work_buffer);
- g_se_mapped_work_buffer_addr = WorkBufferMapBase + (work_buffer_addr & DeviceAddressSpaceAlignMask);
-
- /* Map the work buffer for the SE. */
- R_ASSERT(svcMapDeviceAddressSpaceAligned(g_se_das_hnd, CUR_PROCESS_HANDLE, work_buffer_addr, sizeof(g_work_buffer), g_se_mapped_work_buffer_addr, 3));
- }
-
- /* RSA OAEP implementation helpers. */
- void CalcMgf1AndXor(void *dst, size_t dst_size, const void *src, size_t src_size) {
- uint8_t *dst_u8 = reinterpret_cast(dst);
-
- u32 ctr = 0;
- while (dst_size > 0) {
- size_t cur_size = SHA256_HASH_SIZE;
- if (cur_size > dst_size) {
- cur_size = dst_size;
- }
- dst_size -= cur_size;
-
- u32 ctr_be = __builtin_bswap32(ctr++);
- u8 hash[SHA256_HASH_SIZE];
- {
- Sha256Context ctx;
- sha256ContextCreate(&ctx);
- sha256ContextUpdate(&ctx, src, src_size);
- sha256ContextUpdate(&ctx, &ctr_be, sizeof(ctr_be));
- sha256ContextGetHash(&ctx, hash);
- }
-
- for (size_t i = 0; i < cur_size; i++) {
- *(dst_u8++) ^= hash[i];
- }
- }
- }
-
- size_t DecodeRsaOaep(void *dst, size_t dst_size, const void *label_digest, size_t label_digest_size, const void *src, size_t src_size) {
- /* Very basic validation. */
- if (dst_size == 0 || src_size != 0x100 || label_digest_size != SHA256_HASH_SIZE) {
- return 0;
- }
-
- u8 block[0x100];
- std::memcpy(block, src, sizeof(block));
-
- /* First, validate byte 0 == 0, and unmask DB. */
- int invalid = block[0];
- u8 *salt = block + 1;
- u8 *db = salt + SHA256_HASH_SIZE;
- CalcMgf1AndXor(salt, SHA256_HASH_SIZE, db, src_size - (1 + SHA256_HASH_SIZE));
- CalcMgf1AndXor(db, src_size - (1 + SHA256_HASH_SIZE), salt, SHA256_HASH_SIZE);
-
- /* Validate label digest. */
- for (size_t i = 0; i < SHA256_HASH_SIZE; i++) {
- invalid |= db[i] ^ reinterpret_cast(label_digest)[i];
- }
-
- /* Locate message after 00...0001 padding. */
- const u8 *padded_msg = db + SHA256_HASH_SIZE;
- size_t padded_msg_size = src_size - (1 + 2 * SHA256_HASH_SIZE);
- size_t msg_ind = 0;
- int not_found = 1;
- int wrong_padding = 0;
- size_t i = 0;
- while (i < padded_msg_size) {
- int zero = (padded_msg[i] == 0);
- int one = (padded_msg[i] == 1);
- msg_ind += static_cast(not_found & one) * (++i);
- not_found &= ~one;
- wrong_padding |= (not_found & ~zero);
- }
-
- if (invalid | not_found | wrong_padding) {
- return 0;
- }
-
- /* Copy message out. */
- size_t msg_size = padded_msg_size - msg_ind;
- if (msg_size > dst_size) {
- return 0;
- }
- std::memcpy(dst, padded_msg + msg_ind, msg_size);
- return msg_size;
- }
-
- /* Internal RNG functionality. */
- Result GenerateRandomBytesInternal(void *out, size_t size) {
- if (!g_drbg.GenerateRandomBytes(out, size)) {
- /* We need to reseed. */
- {
- u8 seed[CtrDrbg::SeedSize];
-
- smc::Result res = smc::GenerateRandomBytes(seed, sizeof(seed));
- if (res != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
-
- g_drbg.Reseed(seed);
- g_drbg.GenerateRandomBytes(out, size);
- }
- }
-
- return ResultSuccess;
- }
-
- /* Internal async implementation functionality. */
- void WaitSeOperationComplete() {
- eventWait(&g_se_event, U64_MAX);
- }
-
- smc::Result WaitCheckStatus(smc::AsyncOperationKey op_key) {
- WaitSeOperationComplete();
-
- smc::Result op_res;
- smc::Result res = smc::CheckStatus(&op_res, op_key);
- if (res != smc::Result::Success) {
- return res;
- }
-
- return op_res;
- }
-
- smc::Result WaitGetResult(void *out_buf, size_t out_buf_size, smc::AsyncOperationKey op_key) {
- WaitSeOperationComplete();
-
- smc::Result op_res;
- smc::Result res = smc::GetResult(&op_res, out_buf, out_buf_size, op_key);
- if (res != smc::Result::Success) {
- return res;
- }
-
- return op_res;
- }
-
- /* Internal Keyslot utility. */
- Result ValidateAesKeyslot(u32 keyslot, const void *owner) {
- if (keyslot >= GetMaxKeyslots()) {
- return ResultSplInvalidKeyslot;
- }
- if (g_keyslot_owners[keyslot] != owner && GetRuntimeFirmwareVersion() > FirmwareVersion_100) {
- return ResultSplInvalidKeyslot;
- }
- return ResultSuccess;
- }
-
- /* Helper to do a single AES block decryption. */
- smc::Result DecryptAesBlock(u32 keyslot, void *dst, const void *src) {
- struct DecryptAesBlockLayout {
- SeCryptContext crypt_ctx;
- u8 in_block[AES_BLOCK_SIZE] __attribute__((aligned(AES_BLOCK_SIZE)));
- u8 out_block[AES_BLOCK_SIZE] __attribute__((aligned(AES_BLOCK_SIZE)));
- };
- DecryptAesBlockLayout *layout = reinterpret_cast(g_work_buffer);
-
- layout->crypt_ctx.in.num_entries = 0;
- layout->crypt_ctx.in.address = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, in_block);
- layout->crypt_ctx.in.size = sizeof(layout->in_block);
- layout->crypt_ctx.out.num_entries = 0;
- layout->crypt_ctx.out.address = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, out_block);
- layout->crypt_ctx.out.size = sizeof(layout->out_block);
-
- std::memcpy(layout->in_block, src, sizeof(layout->in_block));
-
- armDCacheFlush(layout, sizeof(*layout));
- {
- std::scoped_lock lk(g_async_op_lock);
- smc::AsyncOperationKey op_key;
- const IvCtr iv_ctr = {};
- const u32 mode = smc::GetCryptAesMode(smc::CipherMode::CbcDecrypt, keyslot);
- const u32 dst_ll_addr = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, crypt_ctx.out);
- const u32 src_ll_addr = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, crypt_ctx.in);
-
- smc::Result res = smc::CryptAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, sizeof(layout->in_block));
- if (res != smc::Result::Success) {
- return res;
- }
-
- if ((res = WaitCheckStatus(op_key)) != smc::Result::Success) {
- return res;
- }
- }
- armDCacheFlush(layout, sizeof(*layout));
-
- std::memcpy(dst, layout->out_block, sizeof(layout->out_block));
- return smc::Result::Success;
- }
-
- /* Implementation wrappers for API commands. */
- Result ImportSecureExpModKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
- struct ImportSecureExpModKeyLayout {
- u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
- };
- ImportSecureExpModKeyLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate size. */
- if (src_size > sizeof(ImportSecureExpModKeyLayout)) {
- return ResultSplInvalidSize;
- }
-
- std::memcpy(layout, src, src_size);
-
- armDCacheFlush(layout, sizeof(*layout));
- smc::Result smc_res;
- if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
- smc_res = smc::DecryptOrImportRsaPrivateKey(layout->data, src_size, access_key, key_source, static_cast(option));
- } else {
- smc_res = smc::ImportSecureExpModKey(layout->data, src_size, access_key, key_source, option);
- }
-
- return smc::ConvertResult(smc_res);
- }
-
- Result SecureExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size, smc::SecureExpModMode mode) {
- struct SecureExpModLayout {
- u8 base[0x100];
- u8 mod[0x100];
- };
- SecureExpModLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate sizes. */
- if (base_size > sizeof(layout->base)) {
- return ResultSplInvalidSize;
- }
- if (mod_size > sizeof(layout->mod)) {
- return ResultSplInvalidSize;
- }
- if (out_size > WorkBufferSizeMax) {
- return ResultSplInvalidSize;
- }
-
- /* Copy data into work buffer. */
- const size_t base_ofs = sizeof(layout->base) - base_size;
- const size_t mod_ofs = sizeof(layout->mod) - mod_size;
- std::memset(layout, 0, sizeof(*layout));
- std::memcpy(layout->base + base_ofs, base, base_size);
- std::memcpy(layout->mod + mod_ofs, mod, mod_size);
-
- /* Do exp mod operation. */
- armDCacheFlush(layout, sizeof(*layout));
- {
- std::scoped_lock lk(g_async_op_lock);
- smc::AsyncOperationKey op_key;
-
- smc::Result res = smc::SecureExpMod(&op_key, layout->base, layout->mod, mode);
- if (res != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
-
- if ((res = WaitGetResult(g_work_buffer, out_size, op_key)) != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
- }
- armDCacheFlush(g_work_buffer, sizeof(out_size));
-
- std::memcpy(out, g_work_buffer, out_size);
- return ResultSuccess;
- }
-
- Result UnwrapEsRsaOaepWrappedKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation, smc::EsKeyType type) {
- struct UnwrapEsKeyLayout {
- u8 base[0x100];
- u8 mod[0x100];
- };
- UnwrapEsKeyLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate sizes. */
- if (base_size > sizeof(layout->base)) {
- return ResultSplInvalidSize;
- }
- if (mod_size > sizeof(layout->mod)) {
- return ResultSplInvalidSize;
- }
- if (label_digest_size > LabelDigestSizeMax) {
- return ResultSplInvalidSize;
- }
-
- /* Copy data into work buffer. */
- const size_t base_ofs = sizeof(layout->base) - base_size;
- const size_t mod_ofs = sizeof(layout->mod) - mod_size;
- std::memset(layout, 0, sizeof(*layout));
- std::memcpy(layout->base + base_ofs, base, base_size);
- std::memcpy(layout->mod + mod_ofs, mod, mod_size);
-
- /* Do exp mod operation. */
- armDCacheFlush(layout, sizeof(*layout));
- {
- std::scoped_lock lk(g_async_op_lock);
- smc::AsyncOperationKey op_key;
-
- smc::Result res = smc::UnwrapTitleKey(&op_key, layout->base, layout->mod, label_digest, label_digest_size, smc::GetUnwrapEsKeyOption(type, generation));
- if (res != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
-
- if ((res = WaitGetResult(g_work_buffer, sizeof(*out_access_key), op_key)) != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
- }
- armDCacheFlush(g_work_buffer, sizeof(*out_access_key));
-
- std::memcpy(out_access_key, g_work_buffer, sizeof(*out_access_key));
- return ResultSuccess;
- }
-
-
- }
-
- /* Initialization. */
- void Initialize() {
- /* Initialize the Drbg. */
- InitializeCtrDrbg();
- /* Initialize SE interrupt + keyslot events. */
- InitializeSeEvents();
- /* Initialize DAS for the SE. */
- InitializeDeviceAddressSpace();
- }
-
- /* General. */
- Result GetConfig(u64 *out, SplConfigItem which) {
- /* Nintendo explicitly blacklists package2 hash here, amusingly. */
- /* This is not blacklisted in safemode, but we're never in safe mode... */
- if (which == SplConfigItem_Package2Hash) {
- return ResultSplInvalidArgument;
- }
-
- smc::Result res = smc::GetConfig(out, 1, which);
-
- /* Nintendo has some special handling here for hardware type/is_retail. */
- if (which == SplConfigItem_HardwareType && res == smc::Result::InvalidArgument) {
- *out = 0;
- res = smc::Result::Success;
- }
- if (which == SplConfigItem_IsRetail && res == smc::Result::InvalidArgument) {
- *out = 0;
- res = smc::Result::Success;
- }
-
- return smc::ConvertResult(res);
- }
-
- Result ExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size) {
- struct ExpModLayout {
- u8 base[0x100];
- u8 exp[0x100];
- u8 mod[0x100];
- };
- ExpModLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate sizes. */
- if (base_size > sizeof(layout->base)) {
- return ResultSplInvalidSize;
- }
- if (exp_size > sizeof(layout->exp)) {
- return ResultSplInvalidSize;
- }
- if (mod_size > sizeof(layout->mod)) {
- return ResultSplInvalidSize;
- }
- if (out_size > WorkBufferSizeMax) {
- return ResultSplInvalidSize;
- }
-
- /* Copy data into work buffer. */
- const size_t base_ofs = sizeof(layout->base) - base_size;
- const size_t mod_ofs = sizeof(layout->mod) - mod_size;
- std::memset(layout, 0, sizeof(*layout));
- std::memcpy(layout->base + base_ofs, base, base_size);
- std::memcpy(layout->exp, exp, exp_size);
- std::memcpy(layout->mod + mod_ofs, mod, mod_size);
-
- /* Do exp mod operation. */
- armDCacheFlush(layout, sizeof(*layout));
- {
- std::scoped_lock lk(g_async_op_lock);
- smc::AsyncOperationKey op_key;
-
- smc::Result res = smc::ExpMod(&op_key, layout->base, layout->exp, exp_size, layout->mod);
- if (res != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
-
- if ((res = WaitGetResult(g_work_buffer, out_size, op_key)) != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
- }
- armDCacheFlush(g_work_buffer, sizeof(out_size));
-
- std::memcpy(out, g_work_buffer, out_size);
- return ResultSuccess;
- }
-
- Result SetConfig(SplConfigItem which, u64 value) {
- return smc::ConvertResult(smc::SetConfig(which, &value, 1));
- }
-
- Result GenerateRandomBytes(void *out, size_t size) {
- u8 *cur_dst = reinterpret_cast(out);
-
- for (size_t ofs = 0; ofs < size; ofs += CtrDrbg::MaxRequestSize) {
- const size_t cur_size = std::min(size - ofs, CtrDrbg::MaxRequestSize);
-
- R_TRY(GenerateRandomBytesInternal(cur_dst, size));
- cur_dst += cur_size;
- }
-
- return ResultSuccess;
- }
-
- Result IsDevelopment(bool *out) {
- u64 is_retail;
- R_TRY(GetConfig(&is_retail, SplConfigItem_IsRetail));
-
- *out = (is_retail == 0);
- return ResultSuccess;
- }
-
- Result SetBootReason(BootReasonValue boot_reason) {
- if (IsBootReasonSet()) {
- return ResultSplBootReasonAlreadySet;
- }
-
- g_boot_reason = boot_reason;
- g_boot_reason_set = true;
- return ResultSuccess;
- }
-
- Result GetBootReason(BootReasonValue *out) {
- if (!IsBootReasonSet()) {
- return ResultSplBootReasonNotSet;
- }
-
- *out = GetBootReason();
- return ResultSuccess;
- }
-
- /* Crypto. */
- Result GenerateAesKek(AccessKey *out_access_key, const KeySource &key_source, u32 generation, u32 option) {
- return smc::ConvertResult(smc::GenerateAesKek(out_access_key, key_source, generation, option));
- }
-
- Result LoadAesKey(u32 keyslot, const void *owner, const AccessKey &access_key, const KeySource &key_source) {
- R_TRY(ValidateAesKeyslot(keyslot, owner));
- return smc::ConvertResult(smc::LoadAesKey(keyslot, access_key, key_source));
- }
-
- Result GenerateAesKey(AesKey *out_key, const AccessKey &access_key, const KeySource &key_source) {
- smc::Result smc_rc;
-
- static const KeySource s_generate_aes_key_source = {
- .data = {0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8}
- };
-
- ScopedAesKeyslot keyslot_holder;
- R_TRY(keyslot_holder.Allocate());
-
- smc_rc = smc::LoadAesKey(keyslot_holder.GetKeyslot(), access_key, s_generate_aes_key_source);
- if (smc_rc == smc::Result::Success) {
- smc_rc = DecryptAesBlock(keyslot_holder.GetKeyslot(), out_key, &key_source);
- }
-
- return smc::ConvertResult(smc_rc);
- }
-
- Result DecryptAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 option) {
- static const KeySource s_decrypt_aes_key_source = {
- .data = {0x11, 0x70, 0x24, 0x2B, 0x48, 0x69, 0x11, 0xF1, 0x11, 0xB0, 0x0C, 0x47, 0x7C, 0xC3, 0xEF, 0x7E}
- };
-
- AccessKey access_key;
- R_TRY(GenerateAesKek(&access_key, s_decrypt_aes_key_source, generation, option));
-
- return GenerateAesKey(out_key, access_key, key_source);
- }
-
- Result CryptAesCtr(void *dst, size_t dst_size, u32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr) {
- R_TRY(ValidateAesKeyslot(keyslot, owner));
-
- /* Succeed immediately if there's nothing to crypt. */
- if (src_size == 0) {
- return ResultSuccess;
- }
-
- /* Validate sizes. */
- if (src_size > dst_size || src_size % AES_BLOCK_SIZE != 0) {
- return ResultSplInvalidSize;
- }
-
- /* We can only map 0x400000 aligned buffers for the SE. With that in mind, we have some math to do. */
- const uintptr_t src_addr = reinterpret_cast(src);
- const uintptr_t dst_addr = reinterpret_cast(dst);
- const uintptr_t src_addr_page_aligned = src_addr & ~0xFFFul;
- const uintptr_t dst_addr_page_aligned = dst_addr & ~0xFFFul;
- const size_t src_size_page_aligned = ((src_addr + src_size + 0xFFFul) & ~0xFFFul) - src_addr_page_aligned;
- const size_t dst_size_page_aligned = ((dst_addr + dst_size + 0xFFFul) & ~0xFFFul) - dst_addr_page_aligned;
- const u32 src_se_map_addr = CryptAesInMapBase + (src_addr_page_aligned & DeviceAddressSpaceAlignMask);
- const u32 dst_se_map_addr = CryptAesOutMapBase + (dst_addr_page_aligned & DeviceAddressSpaceAlignMask);
- const u32 src_se_addr = CryptAesInMapBase + (src_addr & DeviceAddressSpaceAlignMask);
- const u32 dst_se_addr = CryptAesOutMapBase + (dst_addr & DeviceAddressSpaceAlignMask);
-
- /* Validate aligned sizes. */
- if (src_size_page_aligned > CryptAesSizeMax || dst_size_page_aligned > CryptAesSizeMax) {
- return ResultSplInvalidSize;
- }
-
- /* Helpers for mapping/unmapping. */
- DeviceAddressSpaceMapHelper in_mapper(g_se_das_hnd, src_se_map_addr, src_addr_page_aligned, src_size_page_aligned, 1);
- DeviceAddressSpaceMapHelper out_mapper(g_se_das_hnd, dst_se_map_addr, dst_addr_page_aligned, dst_size_page_aligned, 2);
-
- /* Setup SE linked list entries. */
- SeCryptContext *crypt_ctx = reinterpret_cast(g_work_buffer);
- crypt_ctx->in.num_entries = 0;
- crypt_ctx->in.address = src_se_addr;
- crypt_ctx->in.size = src_size;
- crypt_ctx->out.num_entries = 0;
- crypt_ctx->out.address = dst_se_addr;
- crypt_ctx->out.size = dst_size;
-
- armDCacheFlush(crypt_ctx, sizeof(*crypt_ctx));
- armDCacheFlush(const_cast(src), src_size);
- armDCacheFlush(dst, dst_size);
- {
- std::scoped_lock lk(g_async_op_lock);
- smc::AsyncOperationKey op_key;
- const u32 mode = smc::GetCryptAesMode(smc::CipherMode::Ctr, keyslot);
- const u32 dst_ll_addr = g_se_mapped_work_buffer_addr + offsetof(SeCryptContext, out);
- const u32 src_ll_addr = g_se_mapped_work_buffer_addr + offsetof(SeCryptContext, in);
-
- smc::Result res = smc::CryptAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, src_size);
- if (res != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
-
- if ((res = WaitCheckStatus(op_key)) != smc::Result::Success) {
- return smc::ConvertResult(res);
- }
- }
- armDCacheFlush(dst, dst_size);
-
- return ResultSuccess;
- }
-
- Result ComputeCmac(Cmac *out_cmac, u32 keyslot, const void *owner, const void *data, size_t size) {
- R_TRY(ValidateAesKeyslot(keyslot, owner));
-
- if (size > WorkBufferSizeMax) {
- return ResultSplInvalidSize;
- }
-
- std::memcpy(g_work_buffer, data, size);
- return smc::ConvertResult(smc::ComputeCmac(out_cmac, keyslot, g_work_buffer, size));
- }
-
- Result AllocateAesKeyslot(u32 *out_keyslot, const void *owner) {
- if (GetRuntimeFirmwareVersion() <= FirmwareVersion_100) {
- /* On 1.0.0, keyslots were kind of a wild west. */
- *out_keyslot = 0;
- return ResultSuccess;
- }
-
- for (size_t i = 0; i < GetMaxKeyslots(); i++) {
- if (g_keyslot_owners[i] == 0) {
- g_keyslot_owners[i] = owner;
- *out_keyslot = static_cast(i);
- return ResultSuccess;
- }
- }
-
- g_se_keyslot_available_event->Clear();
- return ResultSplOutOfKeyslots;
- }
-
- Result FreeAesKeyslot(u32 keyslot, const void *owner) {
- if (GetRuntimeFirmwareVersion() <= FirmwareVersion_100) {
- /* On 1.0.0, keyslots were kind of a wild west. */
- return ResultSuccess;
- }
-
- R_TRY(ValidateAesKeyslot(keyslot, owner));
-
- /* Clear the keyslot. */
- {
- AccessKey access_key = {};
- KeySource key_source = {};
-
- smc::LoadAesKey(keyslot, access_key, key_source);
- }
- g_keyslot_owners[keyslot] = nullptr;
- g_se_keyslot_available_event->Signal();
- return ResultSuccess;
- }
-
- /* RSA. */
- Result DecryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
- struct DecryptRsaPrivateKeyLayout {
- u8 data[RsaPrivateKeySize + RsaPrivateKeyMetaSize];
- };
- DecryptRsaPrivateKeyLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate size. */
- if (src_size < RsaPrivateKeyMetaSize || src_size > sizeof(DecryptRsaPrivateKeyLayout)) {
- return ResultSplInvalidSize;
- }
-
- std::memcpy(layout->data, src, src_size);
- armDCacheFlush(layout, sizeof(*layout));
-
- smc::Result smc_res;
- size_t copy_size = 0;
- if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
- copy_size = std::min(dst_size, src_size - RsaPrivateKeyMetaSize);
- smc_res = smc::DecryptOrImportRsaPrivateKey(layout->data, src_size, access_key, key_source, smc::DecryptOrImportMode::DecryptRsaPrivateKey);
- } else {
- smc_res = smc::DecryptRsaPrivateKey(©_size, layout->data, src_size, access_key, key_source, option);
- copy_size = std::min(dst_size, copy_size);
- }
-
- armDCacheFlush(layout, sizeof(*layout));
- if (smc_res == smc::Result::Success) {
- std::memcpy(dst, layout->data, copy_size);
- }
-
- return smc::ConvertResult(smc_res);
- }
-
- /* SSL */
- Result ImportSslKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
- return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast(smc::DecryptOrImportMode::ImportSslKey));
- }
-
- Result SslExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
- return SecureExpMod(out, out_size, base, base_size, mod, mod_size, smc::SecureExpModMode::Ssl);
- }
-
- /* ES */
- Result ImportEsKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
- if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
- return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast(smc::DecryptOrImportMode::ImportEsKey));
- } else {
- struct ImportEsKeyLayout {
- u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
- };
- ImportEsKeyLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate size. */
- if (src_size > sizeof(ImportEsKeyLayout)) {
- return ResultSplInvalidSize;
- }
-
- std::memcpy(layout, src, src_size);
-
- armDCacheFlush(layout, sizeof(*layout));
- return smc::ConvertResult(smc::ImportEsKey(layout->data, src_size, access_key, key_source, option));
- }
- }
-
- Result UnwrapTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
- return UnwrapEsRsaOaepWrappedKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsKeyType::TitleKey);
- }
-
- Result UnwrapCommonTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation) {
- return smc::ConvertResult(smc::UnwrapCommonTitleKey(out_access_key, key_source, generation));
- }
-
- Result ImportDrmKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
- return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast(smc::DecryptOrImportMode::ImportDrmKey));
- }
-
- Result DrmExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
- return SecureExpMod(out, out_size, base, base_size, mod, mod_size, smc::SecureExpModMode::Drm);
- }
-
- Result UnwrapElicenseKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
- return UnwrapEsRsaOaepWrappedKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsKeyType::ElicenseKey);
- }
-
- Result LoadElicenseKey(u32 keyslot, const void *owner, const AccessKey &access_key) {
- /* Right now, this is just literally the same function as LoadTitleKey in N's impl. */
- return LoadTitleKey(keyslot, owner, access_key);
- }
-
- /* FS */
- Result ImportLotusKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
- if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
- option = static_cast(smc::DecryptOrImportMode::ImportLotusKey);
- }
- return ImportSecureExpModKey(src, src_size, access_key, key_source, option);
- }
-
- Result DecryptLotusMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size) {
- /* Validate sizes. */
- if (dst_size > WorkBufferSizeMax || label_digest_size != LabelDigestSizeMax) {
- return ResultSplInvalidSize;
- }
-
- /* Nintendo doesn't check this result code, but we will. */
- R_TRY(SecureExpMod(g_work_buffer, 0x100, base, base_size, mod, mod_size, smc::SecureExpModMode::Lotus));
-
- size_t data_size = DecodeRsaOaep(dst, dst_size, label_digest, label_digest_size, g_work_buffer, 0x100);
- if (data_size == 0) {
- return ResultSplDecryptionFailed;
- }
-
- *out_size = static_cast(data_size);
- return ResultSuccess;
- }
-
- Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 which) {
- return smc::ConvertResult(smc::GenerateSpecificAesKey(out_key, key_source, generation, which));
- }
-
- Result LoadTitleKey(u32 keyslot, const void *owner, const AccessKey &access_key) {
- R_TRY(ValidateAesKeyslot(keyslot, owner));
- return smc::ConvertResult(smc::LoadTitleKey(keyslot, access_key));
- }
-
- Result GetPackage2Hash(void *dst, const size_t size) {
- u64 hash[4];
-
- if (size < sizeof(hash)) {
- return ResultSplInvalidSize;
- }
-
- smc::Result smc_res;
- if ((smc_res = smc::GetConfig(hash, 4, SplConfigItem_Package2Hash)) != smc::Result::Success) {
- return smc::ConvertResult(smc_res);
- }
-
- std::memcpy(dst, hash, sizeof(hash));
- return ResultSuccess;
- }
-
- /* Manu. */
- Result ReEncryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option) {
- struct ReEncryptRsaPrivateKeyLayout {
- u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
- AccessKey access_key_dec;
- KeySource source_dec;
- AccessKey access_key_enc;
- KeySource source_enc;
- };
- ReEncryptRsaPrivateKeyLayout *layout = reinterpret_cast(g_work_buffer);
-
- /* Validate size. */
- if (src_size < RsaPrivateKeyMetaSize || src_size > sizeof(ReEncryptRsaPrivateKeyLayout)) {
- return ResultSplInvalidSize;
- }
-
- std::memcpy(layout, src, src_size);
- layout->access_key_dec = access_key_dec;
- layout->source_dec = source_dec;
- layout->access_key_enc = access_key_enc;
- layout->source_enc = source_enc;
-
- armDCacheFlush(layout, sizeof(*layout));
-
- smc::Result smc_res = smc::ReEncryptRsaPrivateKey(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option);
- if (smc_res == smc::Result::Success) {
- size_t copy_size = std::min(dst_size, src_size);
- armDCacheFlush(layout, copy_size);
- std::memcpy(dst, layout->data, copy_size);
- }
-
- return smc::ConvertResult(smc_res);
- }
-
- /* Helper. */
- Result FreeAesKeyslots(const void *owner) {
- for (size_t i = 0; i < GetMaxKeyslots(); i++) {
- if (g_keyslot_owners[i] == owner) {
- FreeAesKeyslot(i, owner);
- }
- }
- return ResultSuccess;
- }
-
- Handle GetAesKeyslotAvailableEventHandle() {
- return g_se_keyslot_available_event->GetHandle();
- }
-
-}
diff --git a/stratosphere/spl/source/spl_api.hpp b/stratosphere/spl/source/spl_api.hpp
deleted file mode 100644
index 63aaaed..0000000
--- a/stratosphere/spl/source/spl_api.hpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-#include
-#include
-
-#include "spl_types.hpp"
-
-namespace sts::spl {
-
- /* Initialization. */
- void Initialize();
-
- /* General. */
- Result GetConfig(u64 *out, SplConfigItem which);
- Result ExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size);
- Result SetConfig(SplConfigItem which, u64 value);
- Result GenerateRandomBytes(void *out, size_t size);
- Result IsDevelopment(bool *out);
- Result SetBootReason(BootReasonValue boot_reason);
- Result GetBootReason(BootReasonValue *out);
-
- /* Crypto. */
- Result GenerateAesKek(AccessKey *out_access_key, const KeySource &key_source, u32 generation, u32 option);
- Result LoadAesKey(u32 keyslot, const void *owner, const AccessKey &access_key, const KeySource &key_source);
- Result GenerateAesKey(AesKey *out_key, const AccessKey &access_key, const KeySource &key_source);
- Result DecryptAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 option);
- Result CryptAesCtr(void *dst, size_t dst_size, u32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr);
- Result ComputeCmac(Cmac *out_cmac, u32 keyslot, const void *owner, const void *data, size_t size);
- Result AllocateAesKeyslot(u32 *out_keyslot, const void *owner);
- Result FreeAesKeyslot(u32 keyslot, const void *owner);
-
- /* RSA. */
- Result DecryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
-
- /* SSL */
- Result ImportSslKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
- Result SslExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
-
- /* ES */
- Result ImportEsKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
- Result UnwrapTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
- Result UnwrapCommonTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation);
- Result ImportDrmKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
- Result DrmExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
- Result UnwrapElicenseKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
- Result LoadElicenseKey(u32 keyslot, const void *owner, const AccessKey &access_key);
-
- /* FS */
- Result ImportLotusKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
- Result DecryptLotusMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size);
- Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 which);
- Result LoadTitleKey(u32 keyslot, const void *owner, const AccessKey &access_key);
- Result GetPackage2Hash(void *dst, const size_t size);
-
- /* Manu. */
- Result ReEncryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option);
-
- /* Helper. */
- Result FreeAesKeyslots(const void *owner);
- Handle GetAesKeyslotAvailableEventHandle();
-
-}
diff --git a/stratosphere/spl/source/spl_api_impl.cpp b/stratosphere/spl/source/spl_api_impl.cpp
new file mode 100644
index 0000000..e6f67a5
--- /dev/null
+++ b/stratosphere/spl/source/spl_api_impl.cpp
@@ -0,0 +1,937 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+
+#include "spl_api_impl.hpp"
+
+#include "spl_ctr_drbg.hpp"
+
+namespace sts::spl::impl {
+
+ namespace {
+
+ /* Convenient defines. */
+ constexpr size_t DeviceAddressSpaceAlignSize = 0x400000;
+ constexpr size_t DeviceAddressSpaceAlignMask = DeviceAddressSpaceAlignSize - 1;
+ constexpr u32 WorkBufferMapBase = 0x80000000u;
+ constexpr u32 CryptAesInMapBase = 0x90000000u;
+ constexpr u32 CryptAesOutMapBase = 0xC0000000u;
+ constexpr size_t CryptAesSizeMax = static_cast(CryptAesOutMapBase - CryptAesInMapBase);
+
+ constexpr size_t RsaPrivateKeySize = 0x100;
+ constexpr size_t RsaPrivateKeyMetaSize = 0x30;
+ constexpr size_t LabelDigestSizeMax = 0x20;
+
+ constexpr size_t WorkBufferSizeMax = 0x800;
+
+ constexpr size_t MaxAesKeyslots = 6;
+ constexpr size_t MaxAesKeyslotsDeprecated = 4;
+
+ /* Max Keyslots helper. */
+ inline size_t GetMaxKeyslots() {
+ return (GetRuntimeFirmwareVersion() >= FirmwareVersion_600) ? MaxAesKeyslots : MaxAesKeyslotsDeprecated;
+ }
+
+ /* Type definitions. */
+ class ScopedAesKeyslot {
+ private:
+ u32 slot;
+ bool has_slot;
+ public:
+ ScopedAesKeyslot() : slot(0), has_slot(false) {
+ /* ... */
+ }
+ ~ScopedAesKeyslot() {
+ if (has_slot) {
+ FreeAesKeyslot(slot, this);
+ }
+ }
+
+ u32 GetKeyslot() const {
+ return this->slot;
+ }
+
+ Result Allocate() {
+ R_TRY(AllocateAesKeyslot(&this->slot, this));
+ this->has_slot = true;
+ return ResultSuccess;
+ }
+ };
+
+ struct SeLinkedListEntry {
+ u32 num_entries;
+ u32 address;
+ u32 size;
+ };
+
+ struct SeCryptContext {
+ SeLinkedListEntry in;
+ SeLinkedListEntry out;
+ };
+
+ class DeviceAddressSpaceMapHelper {
+ private:
+ Handle das_hnd;
+ u64 dst_addr;
+ u64 src_addr;
+ size_t size;
+ u32 perm;
+ public:
+ DeviceAddressSpaceMapHelper(Handle h, u64 dst, u64 src, size_t sz, u32 p) : das_hnd(h), dst_addr(dst), src_addr(src), size(sz), perm(p) {
+ R_ASSERT(svcMapDeviceAddressSpaceAligned(this->das_hnd, CUR_PROCESS_HANDLE, this->src_addr, this->size, this->dst_addr, this->perm));
+ }
+ ~DeviceAddressSpaceMapHelper() {
+ R_ASSERT(svcUnmapDeviceAddressSpace(this->das_hnd, CUR_PROCESS_HANDLE, this->src_addr, this->size, this->dst_addr));
+ }
+ };
+
+ /* Global variables. */
+ CtrDrbg g_drbg;
+ Event g_se_event;
+ IEvent *g_se_keyslot_available_event;
+
+ Handle g_se_das_hnd;
+ u32 g_se_mapped_work_buffer_addr;
+ u8 __attribute__((aligned(0x1000))) g_work_buffer[2 * WorkBufferSizeMax];
+
+ HosMutex g_async_op_lock;
+
+ const void *g_keyslot_owners[MaxAesKeyslots];
+ BootReasonValue g_boot_reason;
+ bool g_boot_reason_set;
+
+ /* Boot Reason accessors. */
+ BootReasonValue GetBootReason() {
+ return g_boot_reason;
+ }
+
+ bool IsBootReasonSet() {
+ return g_boot_reason_set;
+ }
+
+ /* Initialization functionality. */
+ void InitializeCtrDrbg() {
+ u8 seed[CtrDrbg::SeedSize];
+
+ if (smc::GenerateRandomBytes(seed, sizeof(seed)) != smc::Result::Success) {
+ std::abort();
+ }
+
+ g_drbg.Initialize(seed);
+ }
+
+ void InitializeSeEvents() {
+ u64 irq_num;
+ smc::GetConfig(&irq_num, 1, SplConfigItem_SecurityEngineIrqNumber);
+ Handle hnd;
+ R_ASSERT(svcCreateInterruptEvent(&hnd, irq_num, 1));
+ eventLoadRemote(&g_se_event, hnd, true);
+
+ g_se_keyslot_available_event = CreateWriteOnlySystemEvent();
+ g_se_keyslot_available_event->Signal();
+ }
+
+ void InitializeDeviceAddressSpace() {
+ constexpr u64 DeviceName_SE = 29;
+
+ /* Create Address Space. */
+ R_ASSERT(svcCreateDeviceAddressSpace(&g_se_das_hnd, 0, (1ul << 32)));
+
+ /* Attach it to the SE. */
+ R_ASSERT(svcAttachDeviceAddressSpace(DeviceName_SE, g_se_das_hnd));
+
+ const u64 work_buffer_addr = reinterpret_cast(g_work_buffer);
+ g_se_mapped_work_buffer_addr = WorkBufferMapBase + (work_buffer_addr & DeviceAddressSpaceAlignMask);
+
+ /* Map the work buffer for the SE. */
+ R_ASSERT(svcMapDeviceAddressSpaceAligned(g_se_das_hnd, CUR_PROCESS_HANDLE, work_buffer_addr, sizeof(g_work_buffer), g_se_mapped_work_buffer_addr, 3));
+ }
+
+ /* RSA OAEP implementation helpers. */
+ void CalcMgf1AndXor(void *dst, size_t dst_size, const void *src, size_t src_size) {
+ uint8_t *dst_u8 = reinterpret_cast(dst);
+
+ u32 ctr = 0;
+ while (dst_size > 0) {
+ size_t cur_size = SHA256_HASH_SIZE;
+ if (cur_size > dst_size) {
+ cur_size = dst_size;
+ }
+ dst_size -= cur_size;
+
+ u32 ctr_be = __builtin_bswap32(ctr++);
+ u8 hash[SHA256_HASH_SIZE];
+ {
+ Sha256Context ctx;
+ sha256ContextCreate(&ctx);
+ sha256ContextUpdate(&ctx, src, src_size);
+ sha256ContextUpdate(&ctx, &ctr_be, sizeof(ctr_be));
+ sha256ContextGetHash(&ctx, hash);
+ }
+
+ for (size_t i = 0; i < cur_size; i++) {
+ *(dst_u8++) ^= hash[i];
+ }
+ }
+ }
+
+ size_t DecodeRsaOaep(void *dst, size_t dst_size, const void *label_digest, size_t label_digest_size, const void *src, size_t src_size) {
+ /* Very basic validation. */
+ if (dst_size == 0 || src_size != 0x100 || label_digest_size != SHA256_HASH_SIZE) {
+ return 0;
+ }
+
+ u8 block[0x100];
+ std::memcpy(block, src, sizeof(block));
+
+ /* First, validate byte 0 == 0, and unmask DB. */
+ int invalid = block[0];
+ u8 *salt = block + 1;
+ u8 *db = salt + SHA256_HASH_SIZE;
+ CalcMgf1AndXor(salt, SHA256_HASH_SIZE, db, src_size - (1 + SHA256_HASH_SIZE));
+ CalcMgf1AndXor(db, src_size - (1 + SHA256_HASH_SIZE), salt, SHA256_HASH_SIZE);
+
+ /* Validate label digest. */
+ for (size_t i = 0; i < SHA256_HASH_SIZE; i++) {
+ invalid |= db[i] ^ reinterpret_cast(label_digest)[i];
+ }
+
+ /* Locate message after 00...0001 padding. */
+ const u8 *padded_msg = db + SHA256_HASH_SIZE;
+ size_t padded_msg_size = src_size - (1 + 2 * SHA256_HASH_SIZE);
+ size_t msg_ind = 0;
+ int not_found = 1;
+ int wrong_padding = 0;
+ size_t i = 0;
+ while (i < padded_msg_size) {
+ int zero = (padded_msg[i] == 0);
+ int one = (padded_msg[i] == 1);
+ msg_ind += static_cast(not_found & one) * (++i);
+ not_found &= ~one;
+ wrong_padding |= (not_found & ~zero);
+ }
+
+ if (invalid | not_found | wrong_padding) {
+ return 0;
+ }
+
+ /* Copy message out. */
+ size_t msg_size = padded_msg_size - msg_ind;
+ if (msg_size > dst_size) {
+ return 0;
+ }
+ std::memcpy(dst, padded_msg + msg_ind, msg_size);
+ return msg_size;
+ }
+
+ /* Internal RNG functionality. */
+ Result GenerateRandomBytesInternal(void *out, size_t size) {
+ if (!g_drbg.GenerateRandomBytes(out, size)) {
+ /* We need to reseed. */
+ {
+ u8 seed[CtrDrbg::SeedSize];
+
+ smc::Result res = smc::GenerateRandomBytes(seed, sizeof(seed));
+ if (res != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+
+ g_drbg.Reseed(seed);
+ g_drbg.GenerateRandomBytes(out, size);
+ }
+ }
+
+ return ResultSuccess;
+ }
+
+ /* Internal async implementation functionality. */
+ void WaitSeOperationComplete() {
+ eventWait(&g_se_event, U64_MAX);
+ }
+
+ smc::Result WaitCheckStatus(smc::AsyncOperationKey op_key) {
+ WaitSeOperationComplete();
+
+ smc::Result op_res;
+ smc::Result res = smc::CheckStatus(&op_res, op_key);
+ if (res != smc::Result::Success) {
+ return res;
+ }
+
+ return op_res;
+ }
+
+ smc::Result WaitGetResult(void *out_buf, size_t out_buf_size, smc::AsyncOperationKey op_key) {
+ WaitSeOperationComplete();
+
+ smc::Result op_res;
+ smc::Result res = smc::GetResult(&op_res, out_buf, out_buf_size, op_key);
+ if (res != smc::Result::Success) {
+ return res;
+ }
+
+ return op_res;
+ }
+
+ /* Internal Keyslot utility. */
+ Result ValidateAesKeyslot(u32 keyslot, const void *owner) {
+ if (keyslot >= GetMaxKeyslots()) {
+ return ResultSplInvalidKeyslot;
+ }
+ if (g_keyslot_owners[keyslot] != owner && GetRuntimeFirmwareVersion() > FirmwareVersion_100) {
+ return ResultSplInvalidKeyslot;
+ }
+ return ResultSuccess;
+ }
+
+ /* Helper to do a single AES block decryption. */
+ smc::Result DecryptAesBlock(u32 keyslot, void *dst, const void *src) {
+ struct DecryptAesBlockLayout {
+ SeCryptContext crypt_ctx;
+ u8 in_block[AES_BLOCK_SIZE] __attribute__((aligned(AES_BLOCK_SIZE)));
+ u8 out_block[AES_BLOCK_SIZE] __attribute__((aligned(AES_BLOCK_SIZE)));
+ };
+ DecryptAesBlockLayout *layout = reinterpret_cast(g_work_buffer);
+
+ layout->crypt_ctx.in.num_entries = 0;
+ layout->crypt_ctx.in.address = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, in_block);
+ layout->crypt_ctx.in.size = sizeof(layout->in_block);
+ layout->crypt_ctx.out.num_entries = 0;
+ layout->crypt_ctx.out.address = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, out_block);
+ layout->crypt_ctx.out.size = sizeof(layout->out_block);
+
+ std::memcpy(layout->in_block, src, sizeof(layout->in_block));
+
+ armDCacheFlush(layout, sizeof(*layout));
+ {
+ std::scoped_lock lk(g_async_op_lock);
+ smc::AsyncOperationKey op_key;
+ const IvCtr iv_ctr = {};
+ const u32 mode = smc::GetCryptAesMode(smc::CipherMode::CbcDecrypt, keyslot);
+ const u32 dst_ll_addr = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, crypt_ctx.out);
+ const u32 src_ll_addr = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, crypt_ctx.in);
+
+ smc::Result res = smc::CryptAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, sizeof(layout->in_block));
+ if (res != smc::Result::Success) {
+ return res;
+ }
+
+ if ((res = WaitCheckStatus(op_key)) != smc::Result::Success) {
+ return res;
+ }
+ }
+ armDCacheFlush(layout, sizeof(*layout));
+
+ std::memcpy(dst, layout->out_block, sizeof(layout->out_block));
+ return smc::Result::Success;
+ }
+
+ /* Implementation wrappers for API commands. */
+ Result ImportSecureExpModKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
+ struct ImportSecureExpModKeyLayout {
+ u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
+ };
+ ImportSecureExpModKeyLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate size. */
+ if (src_size > sizeof(ImportSecureExpModKeyLayout)) {
+ return ResultSplInvalidSize;
+ }
+
+ std::memcpy(layout, src, src_size);
+
+ armDCacheFlush(layout, sizeof(*layout));
+ smc::Result smc_res;
+ if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
+ smc_res = smc::DecryptOrImportRsaPrivateKey(layout->data, src_size, access_key, key_source, static_cast(option));
+ } else {
+ smc_res = smc::ImportSecureExpModKey(layout->data, src_size, access_key, key_source, option);
+ }
+
+ return smc::ConvertResult(smc_res);
+ }
+
+ Result SecureExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size, smc::SecureExpModMode mode) {
+ struct SecureExpModLayout {
+ u8 base[0x100];
+ u8 mod[0x100];
+ };
+ SecureExpModLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate sizes. */
+ if (base_size > sizeof(layout->base)) {
+ return ResultSplInvalidSize;
+ }
+ if (mod_size > sizeof(layout->mod)) {
+ return ResultSplInvalidSize;
+ }
+ if (out_size > WorkBufferSizeMax) {
+ return ResultSplInvalidSize;
+ }
+
+ /* Copy data into work buffer. */
+ const size_t base_ofs = sizeof(layout->base) - base_size;
+ const size_t mod_ofs = sizeof(layout->mod) - mod_size;
+ std::memset(layout, 0, sizeof(*layout));
+ std::memcpy(layout->base + base_ofs, base, base_size);
+ std::memcpy(layout->mod + mod_ofs, mod, mod_size);
+
+ /* Do exp mod operation. */
+ armDCacheFlush(layout, sizeof(*layout));
+ {
+ std::scoped_lock lk(g_async_op_lock);
+ smc::AsyncOperationKey op_key;
+
+ smc::Result res = smc::SecureExpMod(&op_key, layout->base, layout->mod, mode);
+ if (res != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+
+ if ((res = WaitGetResult(g_work_buffer, out_size, op_key)) != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+ }
+ armDCacheFlush(g_work_buffer, sizeof(out_size));
+
+ std::memcpy(out, g_work_buffer, out_size);
+ return ResultSuccess;
+ }
+
+ Result UnwrapEsRsaOaepWrappedKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation, smc::EsKeyType type) {
+ struct UnwrapEsKeyLayout {
+ u8 base[0x100];
+ u8 mod[0x100];
+ };
+ UnwrapEsKeyLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate sizes. */
+ if (base_size > sizeof(layout->base)) {
+ return ResultSplInvalidSize;
+ }
+ if (mod_size > sizeof(layout->mod)) {
+ return ResultSplInvalidSize;
+ }
+ if (label_digest_size > LabelDigestSizeMax) {
+ return ResultSplInvalidSize;
+ }
+
+ /* Copy data into work buffer. */
+ const size_t base_ofs = sizeof(layout->base) - base_size;
+ const size_t mod_ofs = sizeof(layout->mod) - mod_size;
+ std::memset(layout, 0, sizeof(*layout));
+ std::memcpy(layout->base + base_ofs, base, base_size);
+ std::memcpy(layout->mod + mod_ofs, mod, mod_size);
+
+ /* Do exp mod operation. */
+ armDCacheFlush(layout, sizeof(*layout));
+ {
+ std::scoped_lock lk(g_async_op_lock);
+ smc::AsyncOperationKey op_key;
+
+ smc::Result res = smc::UnwrapTitleKey(&op_key, layout->base, layout->mod, label_digest, label_digest_size, smc::GetUnwrapEsKeyOption(type, generation));
+ if (res != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+
+ if ((res = WaitGetResult(g_work_buffer, sizeof(*out_access_key), op_key)) != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+ }
+ armDCacheFlush(g_work_buffer, sizeof(*out_access_key));
+
+ std::memcpy(out_access_key, g_work_buffer, sizeof(*out_access_key));
+ return ResultSuccess;
+ }
+
+
+ }
+
+ /* Initialization. */
+ void Initialize() {
+ /* Initialize the Drbg. */
+ InitializeCtrDrbg();
+ /* Initialize SE interrupt + keyslot events. */
+ InitializeSeEvents();
+ /* Initialize DAS for the SE. */
+ InitializeDeviceAddressSpace();
+ }
+
+ /* General. */
+ Result GetConfig(u64 *out, SplConfigItem which) {
+ /* Nintendo explicitly blacklists package2 hash here, amusingly. */
+ /* This is not blacklisted in safemode, but we're never in safe mode... */
+ if (which == SplConfigItem_Package2Hash) {
+ return ResultSplInvalidArgument;
+ }
+
+ smc::Result res = smc::GetConfig(out, 1, which);
+
+ /* Nintendo has some special handling here for hardware type/is_retail. */
+ if (which == SplConfigItem_HardwareType && res == smc::Result::InvalidArgument) {
+ *out = 0;
+ res = smc::Result::Success;
+ }
+ if (which == SplConfigItem_IsRetail && res == smc::Result::InvalidArgument) {
+ *out = 0;
+ res = smc::Result::Success;
+ }
+
+ return smc::ConvertResult(res);
+ }
+
+ Result ExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size) {
+ struct ExpModLayout {
+ u8 base[0x100];
+ u8 exp[0x100];
+ u8 mod[0x100];
+ };
+ ExpModLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate sizes. */
+ if (base_size > sizeof(layout->base)) {
+ return ResultSplInvalidSize;
+ }
+ if (exp_size > sizeof(layout->exp)) {
+ return ResultSplInvalidSize;
+ }
+ if (mod_size > sizeof(layout->mod)) {
+ return ResultSplInvalidSize;
+ }
+ if (out_size > WorkBufferSizeMax) {
+ return ResultSplInvalidSize;
+ }
+
+ /* Copy data into work buffer. */
+ const size_t base_ofs = sizeof(layout->base) - base_size;
+ const size_t mod_ofs = sizeof(layout->mod) - mod_size;
+ std::memset(layout, 0, sizeof(*layout));
+ std::memcpy(layout->base + base_ofs, base, base_size);
+ std::memcpy(layout->exp, exp, exp_size);
+ std::memcpy(layout->mod + mod_ofs, mod, mod_size);
+
+ /* Do exp mod operation. */
+ armDCacheFlush(layout, sizeof(*layout));
+ {
+ std::scoped_lock lk(g_async_op_lock);
+ smc::AsyncOperationKey op_key;
+
+ smc::Result res = smc::ExpMod(&op_key, layout->base, layout->exp, exp_size, layout->mod);
+ if (res != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+
+ if ((res = WaitGetResult(g_work_buffer, out_size, op_key)) != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+ }
+ armDCacheFlush(g_work_buffer, sizeof(out_size));
+
+ std::memcpy(out, g_work_buffer, out_size);
+ return ResultSuccess;
+ }
+
+ Result SetConfig(SplConfigItem which, u64 value) {
+ return smc::ConvertResult(smc::SetConfig(which, &value, 1));
+ }
+
+ Result GenerateRandomBytes(void *out, size_t size) {
+ u8 *cur_dst = reinterpret_cast(out);
+
+ for (size_t ofs = 0; ofs < size; ofs += CtrDrbg::MaxRequestSize) {
+ const size_t cur_size = std::min(size - ofs, CtrDrbg::MaxRequestSize);
+
+ R_TRY(GenerateRandomBytesInternal(cur_dst, size));
+ cur_dst += cur_size;
+ }
+
+ return ResultSuccess;
+ }
+
+ Result IsDevelopment(bool *out) {
+ u64 is_retail;
+ R_TRY(GetConfig(&is_retail, SplConfigItem_IsRetail));
+
+ *out = (is_retail == 0);
+ return ResultSuccess;
+ }
+
+ Result SetBootReason(BootReasonValue boot_reason) {
+ if (IsBootReasonSet()) {
+ return ResultSplBootReasonAlreadySet;
+ }
+
+ g_boot_reason = boot_reason;
+ g_boot_reason_set = true;
+ return ResultSuccess;
+ }
+
+ Result GetBootReason(BootReasonValue *out) {
+ if (!IsBootReasonSet()) {
+ return ResultSplBootReasonNotSet;
+ }
+
+ *out = GetBootReason();
+ return ResultSuccess;
+ }
+
+ /* Crypto. */
+ Result GenerateAesKek(AccessKey *out_access_key, const KeySource &key_source, u32 generation, u32 option) {
+ return smc::ConvertResult(smc::GenerateAesKek(out_access_key, key_source, generation, option));
+ }
+
+ Result LoadAesKey(u32 keyslot, const void *owner, const AccessKey &access_key, const KeySource &key_source) {
+ R_TRY(ValidateAesKeyslot(keyslot, owner));
+ return smc::ConvertResult(smc::LoadAesKey(keyslot, access_key, key_source));
+ }
+
+ Result GenerateAesKey(AesKey *out_key, const AccessKey &access_key, const KeySource &key_source) {
+ smc::Result smc_rc;
+
+ static const KeySource s_generate_aes_key_source = {
+ .data = {0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8}
+ };
+
+ ScopedAesKeyslot keyslot_holder;
+ R_TRY(keyslot_holder.Allocate());
+
+ smc_rc = smc::LoadAesKey(keyslot_holder.GetKeyslot(), access_key, s_generate_aes_key_source);
+ if (smc_rc == smc::Result::Success) {
+ smc_rc = DecryptAesBlock(keyslot_holder.GetKeyslot(), out_key, &key_source);
+ }
+
+ return smc::ConvertResult(smc_rc);
+ }
+
+ Result DecryptAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 option) {
+ static const KeySource s_decrypt_aes_key_source = {
+ .data = {0x11, 0x70, 0x24, 0x2B, 0x48, 0x69, 0x11, 0xF1, 0x11, 0xB0, 0x0C, 0x47, 0x7C, 0xC3, 0xEF, 0x7E}
+ };
+
+ AccessKey access_key;
+ R_TRY(GenerateAesKek(&access_key, s_decrypt_aes_key_source, generation, option));
+
+ return GenerateAesKey(out_key, access_key, key_source);
+ }
+
+ Result CryptAesCtr(void *dst, size_t dst_size, u32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr) {
+ R_TRY(ValidateAesKeyslot(keyslot, owner));
+
+ /* Succeed immediately if there's nothing to crypt. */
+ if (src_size == 0) {
+ return ResultSuccess;
+ }
+
+ /* Validate sizes. */
+ if (src_size > dst_size || src_size % AES_BLOCK_SIZE != 0) {
+ return ResultSplInvalidSize;
+ }
+
+ /* We can only map 0x400000 aligned buffers for the SE. With that in mind, we have some math to do. */
+ const uintptr_t src_addr = reinterpret_cast(src);
+ const uintptr_t dst_addr = reinterpret_cast(dst);
+ const uintptr_t src_addr_page_aligned = src_addr & ~0xFFFul;
+ const uintptr_t dst_addr_page_aligned = dst_addr & ~0xFFFul;
+ const size_t src_size_page_aligned = ((src_addr + src_size + 0xFFFul) & ~0xFFFul) - src_addr_page_aligned;
+ const size_t dst_size_page_aligned = ((dst_addr + dst_size + 0xFFFul) & ~0xFFFul) - dst_addr_page_aligned;
+ const u32 src_se_map_addr = CryptAesInMapBase + (src_addr_page_aligned & DeviceAddressSpaceAlignMask);
+ const u32 dst_se_map_addr = CryptAesOutMapBase + (dst_addr_page_aligned & DeviceAddressSpaceAlignMask);
+ const u32 src_se_addr = CryptAesInMapBase + (src_addr & DeviceAddressSpaceAlignMask);
+ const u32 dst_se_addr = CryptAesOutMapBase + (dst_addr & DeviceAddressSpaceAlignMask);
+
+ /* Validate aligned sizes. */
+ if (src_size_page_aligned > CryptAesSizeMax || dst_size_page_aligned > CryptAesSizeMax) {
+ return ResultSplInvalidSize;
+ }
+
+ /* Helpers for mapping/unmapping. */
+ DeviceAddressSpaceMapHelper in_mapper(g_se_das_hnd, src_se_map_addr, src_addr_page_aligned, src_size_page_aligned, 1);
+ DeviceAddressSpaceMapHelper out_mapper(g_se_das_hnd, dst_se_map_addr, dst_addr_page_aligned, dst_size_page_aligned, 2);
+
+ /* Setup SE linked list entries. */
+ SeCryptContext *crypt_ctx = reinterpret_cast(g_work_buffer);
+ crypt_ctx->in.num_entries = 0;
+ crypt_ctx->in.address = src_se_addr;
+ crypt_ctx->in.size = src_size;
+ crypt_ctx->out.num_entries = 0;
+ crypt_ctx->out.address = dst_se_addr;
+ crypt_ctx->out.size = dst_size;
+
+ armDCacheFlush(crypt_ctx, sizeof(*crypt_ctx));
+ armDCacheFlush(const_cast(src), src_size);
+ armDCacheFlush(dst, dst_size);
+ {
+ std::scoped_lock lk(g_async_op_lock);
+ smc::AsyncOperationKey op_key;
+ const u32 mode = smc::GetCryptAesMode(smc::CipherMode::Ctr, keyslot);
+ const u32 dst_ll_addr = g_se_mapped_work_buffer_addr + offsetof(SeCryptContext, out);
+ const u32 src_ll_addr = g_se_mapped_work_buffer_addr + offsetof(SeCryptContext, in);
+
+ smc::Result res = smc::CryptAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, src_size);
+ if (res != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+
+ if ((res = WaitCheckStatus(op_key)) != smc::Result::Success) {
+ return smc::ConvertResult(res);
+ }
+ }
+ armDCacheFlush(dst, dst_size);
+
+ return ResultSuccess;
+ }
+
+ Result ComputeCmac(Cmac *out_cmac, u32 keyslot, const void *owner, const void *data, size_t size) {
+ R_TRY(ValidateAesKeyslot(keyslot, owner));
+
+ if (size > WorkBufferSizeMax) {
+ return ResultSplInvalidSize;
+ }
+
+ std::memcpy(g_work_buffer, data, size);
+ return smc::ConvertResult(smc::ComputeCmac(out_cmac, keyslot, g_work_buffer, size));
+ }
+
+ Result AllocateAesKeyslot(u32 *out_keyslot, const void *owner) {
+ if (GetRuntimeFirmwareVersion() <= FirmwareVersion_100) {
+ /* On 1.0.0, keyslots were kind of a wild west. */
+ *out_keyslot = 0;
+ return ResultSuccess;
+ }
+
+ for (size_t i = 0; i < GetMaxKeyslots(); i++) {
+ if (g_keyslot_owners[i] == 0) {
+ g_keyslot_owners[i] = owner;
+ *out_keyslot = static_cast(i);
+ return ResultSuccess;
+ }
+ }
+
+ g_se_keyslot_available_event->Clear();
+ return ResultSplOutOfKeyslots;
+ }
+
+ Result FreeAesKeyslot(u32 keyslot, const void *owner) {
+ if (GetRuntimeFirmwareVersion() <= FirmwareVersion_100) {
+ /* On 1.0.0, keyslots were kind of a wild west. */
+ return ResultSuccess;
+ }
+
+ R_TRY(ValidateAesKeyslot(keyslot, owner));
+
+ /* Clear the keyslot. */
+ {
+ AccessKey access_key = {};
+ KeySource key_source = {};
+
+ smc::LoadAesKey(keyslot, access_key, key_source);
+ }
+ g_keyslot_owners[keyslot] = nullptr;
+ g_se_keyslot_available_event->Signal();
+ return ResultSuccess;
+ }
+
+ /* RSA. */
+ Result DecryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
+ struct DecryptRsaPrivateKeyLayout {
+ u8 data[RsaPrivateKeySize + RsaPrivateKeyMetaSize];
+ };
+ DecryptRsaPrivateKeyLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate size. */
+ if (src_size < RsaPrivateKeyMetaSize || src_size > sizeof(DecryptRsaPrivateKeyLayout)) {
+ return ResultSplInvalidSize;
+ }
+
+ std::memcpy(layout->data, src, src_size);
+ armDCacheFlush(layout, sizeof(*layout));
+
+ smc::Result smc_res;
+ size_t copy_size = 0;
+ if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
+ copy_size = std::min(dst_size, src_size - RsaPrivateKeyMetaSize);
+ smc_res = smc::DecryptOrImportRsaPrivateKey(layout->data, src_size, access_key, key_source, smc::DecryptOrImportMode::DecryptRsaPrivateKey);
+ } else {
+ smc_res = smc::DecryptRsaPrivateKey(©_size, layout->data, src_size, access_key, key_source, option);
+ copy_size = std::min(dst_size, copy_size);
+ }
+
+ armDCacheFlush(layout, sizeof(*layout));
+ if (smc_res == smc::Result::Success) {
+ std::memcpy(dst, layout->data, copy_size);
+ }
+
+ return smc::ConvertResult(smc_res);
+ }
+
+ /* SSL */
+ Result ImportSslKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
+ return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast(smc::DecryptOrImportMode::ImportSslKey));
+ }
+
+ Result SslExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
+ return SecureExpMod(out, out_size, base, base_size, mod, mod_size, smc::SecureExpModMode::Ssl);
+ }
+
+ /* ES */
+ Result ImportEsKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
+ if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
+ return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast(smc::DecryptOrImportMode::ImportEsKey));
+ } else {
+ struct ImportEsKeyLayout {
+ u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
+ };
+ ImportEsKeyLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate size. */
+ if (src_size > sizeof(ImportEsKeyLayout)) {
+ return ResultSplInvalidSize;
+ }
+
+ std::memcpy(layout, src, src_size);
+
+ armDCacheFlush(layout, sizeof(*layout));
+ return smc::ConvertResult(smc::ImportEsKey(layout->data, src_size, access_key, key_source, option));
+ }
+ }
+
+ Result UnwrapTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
+ return UnwrapEsRsaOaepWrappedKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsKeyType::TitleKey);
+ }
+
+ Result UnwrapCommonTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation) {
+ return smc::ConvertResult(smc::UnwrapCommonTitleKey(out_access_key, key_source, generation));
+ }
+
+ Result ImportDrmKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
+ return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast(smc::DecryptOrImportMode::ImportDrmKey));
+ }
+
+ Result DrmExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
+ return SecureExpMod(out, out_size, base, base_size, mod, mod_size, smc::SecureExpModMode::Drm);
+ }
+
+ Result UnwrapElicenseKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
+ return UnwrapEsRsaOaepWrappedKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsKeyType::ElicenseKey);
+ }
+
+ Result LoadElicenseKey(u32 keyslot, const void *owner, const AccessKey &access_key) {
+ /* Right now, this is just literally the same function as LoadTitleKey in N's impl. */
+ return LoadTitleKey(keyslot, owner, access_key);
+ }
+
+ /* FS */
+ Result ImportLotusKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
+ if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
+ option = static_cast(smc::DecryptOrImportMode::ImportLotusKey);
+ }
+ return ImportSecureExpModKey(src, src_size, access_key, key_source, option);
+ }
+
+ Result DecryptLotusMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size) {
+ /* Validate sizes. */
+ if (dst_size > WorkBufferSizeMax || label_digest_size != LabelDigestSizeMax) {
+ return ResultSplInvalidSize;
+ }
+
+ /* Nintendo doesn't check this result code, but we will. */
+ R_TRY(SecureExpMod(g_work_buffer, 0x100, base, base_size, mod, mod_size, smc::SecureExpModMode::Lotus));
+
+ size_t data_size = DecodeRsaOaep(dst, dst_size, label_digest, label_digest_size, g_work_buffer, 0x100);
+ if (data_size == 0) {
+ return ResultSplDecryptionFailed;
+ }
+
+ *out_size = static_cast(data_size);
+ return ResultSuccess;
+ }
+
+ Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 which) {
+ return smc::ConvertResult(smc::GenerateSpecificAesKey(out_key, key_source, generation, which));
+ }
+
+ Result LoadTitleKey(u32 keyslot, const void *owner, const AccessKey &access_key) {
+ R_TRY(ValidateAesKeyslot(keyslot, owner));
+ return smc::ConvertResult(smc::LoadTitleKey(keyslot, access_key));
+ }
+
+ Result GetPackage2Hash(void *dst, const size_t size) {
+ u64 hash[4];
+
+ if (size < sizeof(hash)) {
+ return ResultSplInvalidSize;
+ }
+
+ smc::Result smc_res;
+ if ((smc_res = smc::GetConfig(hash, 4, SplConfigItem_Package2Hash)) != smc::Result::Success) {
+ return smc::ConvertResult(smc_res);
+ }
+
+ std::memcpy(dst, hash, sizeof(hash));
+ return ResultSuccess;
+ }
+
+ /* Manu. */
+ Result ReEncryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option) {
+ struct ReEncryptRsaPrivateKeyLayout {
+ u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
+ AccessKey access_key_dec;
+ KeySource source_dec;
+ AccessKey access_key_enc;
+ KeySource source_enc;
+ };
+ ReEncryptRsaPrivateKeyLayout *layout = reinterpret_cast(g_work_buffer);
+
+ /* Validate size. */
+ if (src_size < RsaPrivateKeyMetaSize || src_size > sizeof(ReEncryptRsaPrivateKeyLayout)) {
+ return ResultSplInvalidSize;
+ }
+
+ std::memcpy(layout, src, src_size);
+ layout->access_key_dec = access_key_dec;
+ layout->source_dec = source_dec;
+ layout->access_key_enc = access_key_enc;
+ layout->source_enc = source_enc;
+
+ armDCacheFlush(layout, sizeof(*layout));
+
+ smc::Result smc_res = smc::ReEncryptRsaPrivateKey(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option);
+ if (smc_res == smc::Result::Success) {
+ size_t copy_size = std::min(dst_size, src_size);
+ armDCacheFlush(layout, copy_size);
+ std::memcpy(dst, layout->data, copy_size);
+ }
+
+ return smc::ConvertResult(smc_res);
+ }
+
+ /* Helper. */
+ Result FreeAesKeyslots(const void *owner) {
+ for (size_t i = 0; i < GetMaxKeyslots(); i++) {
+ if (g_keyslot_owners[i] == owner) {
+ FreeAesKeyslot(i, owner);
+ }
+ }
+ return ResultSuccess;
+ }
+
+ Handle GetAesKeyslotAvailableEventHandle() {
+ return g_se_keyslot_available_event->GetHandle();
+ }
+
+}
diff --git a/stratosphere/spl/source/spl_api_impl.hpp b/stratosphere/spl/source/spl_api_impl.hpp
new file mode 100644
index 0000000..8ef033f
--- /dev/null
+++ b/stratosphere/spl/source/spl_api_impl.hpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+#include
+
+namespace sts::spl::impl {
+
+ /* Initialization. */
+ void Initialize();
+
+ /* General. */
+ Result GetConfig(u64 *out, SplConfigItem which);
+ Result ExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size);
+ Result SetConfig(SplConfigItem which, u64 value);
+ Result GenerateRandomBytes(void *out, size_t size);
+ Result IsDevelopment(bool *out);
+ Result SetBootReason(BootReasonValue boot_reason);
+ Result GetBootReason(BootReasonValue *out);
+
+ /* Crypto. */
+ Result GenerateAesKek(AccessKey *out_access_key, const KeySource &key_source, u32 generation, u32 option);
+ Result LoadAesKey(u32 keyslot, const void *owner, const AccessKey &access_key, const KeySource &key_source);
+ Result GenerateAesKey(AesKey *out_key, const AccessKey &access_key, const KeySource &key_source);
+ Result DecryptAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 option);
+ Result CryptAesCtr(void *dst, size_t dst_size, u32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr);
+ Result ComputeCmac(Cmac *out_cmac, u32 keyslot, const void *owner, const void *data, size_t size);
+ Result AllocateAesKeyslot(u32 *out_keyslot, const void *owner);
+ Result FreeAesKeyslot(u32 keyslot, const void *owner);
+
+ /* RSA. */
+ Result DecryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
+
+ /* SSL */
+ Result ImportSslKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
+ Result SslExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
+
+ /* ES */
+ Result ImportEsKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
+ Result UnwrapTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
+ Result UnwrapCommonTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation);
+ Result ImportDrmKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
+ Result DrmExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
+ Result UnwrapElicenseKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
+ Result LoadElicenseKey(u32 keyslot, const void *owner, const AccessKey &access_key);
+
+ /* FS */
+ Result ImportLotusKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
+ Result DecryptLotusMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size);
+ Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 which);
+ Result LoadTitleKey(u32 keyslot, const void *owner, const AccessKey &access_key);
+ Result GetPackage2Hash(void *dst, const size_t size);
+
+ /* Manu. */
+ Result ReEncryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option);
+
+ /* Helper. */
+ Result FreeAesKeyslots(const void *owner);
+ Handle GetAesKeyslotAvailableEventHandle();
+
+}
diff --git a/stratosphere/spl/source/spl_crypto_service.cpp b/stratosphere/spl/source/spl_crypto_service.cpp
index 86e445e..8dacd4b 100644
--- a/stratosphere/spl/source/spl_crypto_service.cpp
+++ b/stratosphere/spl/source/spl_crypto_service.cpp
@@ -17,50 +17,50 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_crypto_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
CryptoService::~CryptoService() {
/* Free any keyslots this service is using. */
- spl::FreeAesKeyslots(this);
+ impl::FreeAesKeyslots(this);
}
Result CryptoService::GenerateAesKek(Out out_access_key, KeySource key_source, u32 generation, u32 option) {
- return spl::GenerateAesKek(out_access_key.GetPointer(), key_source, generation, option);
+ return impl::GenerateAesKek(out_access_key.GetPointer(), key_source, generation, option);
}
Result CryptoService::LoadAesKey(u32 keyslot, AccessKey access_key, KeySource key_source) {
- return spl::LoadAesKey(keyslot, this, access_key, key_source);
+ return impl::LoadAesKey(keyslot, this, access_key, key_source);
}
Result CryptoService::GenerateAesKey(Out out_key, AccessKey access_key, KeySource key_source) {
- return spl::GenerateAesKey(out_key.GetPointer(), access_key, key_source);
+ return impl::GenerateAesKey(out_key.GetPointer(), access_key, key_source);
}
Result CryptoService::DecryptAesKey(Out out_key, KeySource key_source, u32 generation, u32 option) {
- return spl::DecryptAesKey(out_key.GetPointer(), key_source, generation, option);
+ return impl::DecryptAesKey(out_key.GetPointer(), key_source, generation, option);
}
Result CryptoService::CryptAesCtr(OutBuffer out_buf, u32 keyslot, InBuffer in_buf, IvCtr iv_ctr) {
- return spl::CryptAesCtr(out_buf.buffer, out_buf.num_elements, keyslot, this, in_buf.buffer, in_buf.num_elements, iv_ctr);
+ return impl::CryptAesCtr(out_buf.buffer, out_buf.num_elements, keyslot, this, in_buf.buffer, in_buf.num_elements, iv_ctr);
}
Result CryptoService::ComputeCmac(Out out_cmac, u32 keyslot, InPointer in_buf) {
- return spl::ComputeCmac(out_cmac.GetPointer(), keyslot, this, in_buf.pointer, in_buf.num_elements);
+ return impl::ComputeCmac(out_cmac.GetPointer(), keyslot, this, in_buf.pointer, in_buf.num_elements);
}
Result CryptoService::AllocateAesKeyslot(Out out_keyslot) {
- return spl::AllocateAesKeyslot(out_keyslot.GetPointer(), this);
+ return impl::AllocateAesKeyslot(out_keyslot.GetPointer(), this);
}
Result CryptoService::FreeAesKeyslot(u32 keyslot) {
- return spl::FreeAesKeyslot(keyslot, this);
+ return impl::FreeAesKeyslot(keyslot, this);
}
void CryptoService::GetAesKeyslotAvailableEvent(Out out_hnd) {
- out_hnd.SetValue(spl::GetAesKeyslotAvailableEventHandle());
+ out_hnd.SetValue(impl::GetAesKeyslotAvailableEventHandle());
}
}
diff --git a/stratosphere/spl/source/spl_crypto_service.hpp b/stratosphere/spl/source/spl_crypto_service.hpp
index 3acfb1f..c5ad23b 100644
--- a/stratosphere/spl/source/spl_crypto_service.hpp
+++ b/stratosphere/spl/source/spl_crypto_service.hpp
@@ -17,8 +17,8 @@
#pragma once
#include
#include
+#include
-#include "spl_types.hpp"
#include "spl_general_service.hpp"
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_ctr_drbg.cpp b/stratosphere/spl/source/spl_ctr_drbg.cpp
index c9bc732..72ad9f7 100644
--- a/stratosphere/spl/source/spl_ctr_drbg.cpp
+++ b/stratosphere/spl/source/spl_ctr_drbg.cpp
@@ -16,8 +16,8 @@
#include
#include
+#include
-#include "spl_types.hpp"
#include "spl_ctr_drbg.hpp"
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_ctr_drbg.hpp b/stratosphere/spl/source/spl_ctr_drbg.hpp
index 462c3c2..2bbff9d 100644
--- a/stratosphere/spl/source/spl_ctr_drbg.hpp
+++ b/stratosphere/spl/source/spl_ctr_drbg.hpp
@@ -17,8 +17,7 @@
#pragma once
#include
#include
-
-#include "spl_types.hpp"
+#include
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_deprecated_service.cpp b/stratosphere/spl/source/spl_deprecated_service.cpp
index 5aa7234..21bcff2 100644
--- a/stratosphere/spl/source/spl_deprecated_service.cpp
+++ b/stratosphere/spl/source/spl_deprecated_service.cpp
@@ -17,109 +17,109 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_deprecated_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result DeprecatedService::GetConfig(Out out, u32 which) {
- return spl::GetConfig(out.GetPointer(), static_cast(which));
+ return impl::GetConfig(out.GetPointer(), static_cast(which));
}
Result DeprecatedService::ExpMod(OutPointerWithClientSize out, InPointer base, InPointer exp, InPointer mod) {
- return spl::ExpMod(out.pointer, out.num_elements, base.pointer, base.num_elements, exp.pointer, exp.num_elements, mod.pointer, mod.num_elements);
+ return impl::ExpMod(out.pointer, out.num_elements, base.pointer, base.num_elements, exp.pointer, exp.num_elements, mod.pointer, mod.num_elements);
}
Result DeprecatedService::GenerateAesKek(Out out_access_key, KeySource key_source, u32 generation, u32 option) {
- return spl::GenerateAesKek(out_access_key.GetPointer(), key_source, generation, option);
+ return impl::GenerateAesKek(out_access_key.GetPointer(), key_source, generation, option);
}
Result DeprecatedService::LoadAesKey(u32 keyslot, AccessKey access_key, KeySource key_source) {
- return spl::LoadAesKey(keyslot, this, access_key, key_source);
+ return impl::LoadAesKey(keyslot, this, access_key, key_source);
}
Result DeprecatedService::GenerateAesKey(Out out_key, AccessKey access_key, KeySource key_source) {
- return spl::GenerateAesKey(out_key.GetPointer(), access_key, key_source);
+ return impl::GenerateAesKey(out_key.GetPointer(), access_key, key_source);
}
Result DeprecatedService::SetConfig(u32 which, u64 value) {
- return spl::SetConfig(static_cast(which), value);
+ return impl::SetConfig(static_cast(which), value);
}
Result DeprecatedService::GenerateRandomBytes(OutPointerWithClientSize out) {
- return spl::GenerateRandomBytes(out.pointer, out.num_elements);
+ return impl::GenerateRandomBytes(out.pointer, out.num_elements);
}
Result DeprecatedService::ImportLotusKey(InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
- return spl::ImportLotusKey(src.pointer, src.num_elements, access_key, key_source, option);
+ return impl::ImportLotusKey(src.pointer, src.num_elements, access_key, key_source, option);
}
Result DeprecatedService::DecryptLotusMessage(Out out_size, OutPointerWithClientSize out, InPointer base, InPointer mod, InPointer label_digest) {
- return spl::DecryptLotusMessage(out_size.GetPointer(), out.pointer, out.num_elements, base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements);
+ return impl::DecryptLotusMessage(out_size.GetPointer(), out.pointer, out.num_elements, base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements);
}
Result DeprecatedService::IsDevelopment(Out is_dev) {
- return spl::IsDevelopment(is_dev.GetPointer());
+ return impl::IsDevelopment(is_dev.GetPointer());
}
Result DeprecatedService::GenerateSpecificAesKey(Out out_key, KeySource key_source, u32 generation, u32 which) {
- return spl::GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
+ return impl::GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
}
Result DeprecatedService::DecryptRsaPrivateKey(OutPointerWithClientSize dst, InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
- return spl::DecryptRsaPrivateKey(dst.pointer, dst.num_elements, src.pointer, src.num_elements, access_key, key_source, option);
+ return impl::DecryptRsaPrivateKey(dst.pointer, dst.num_elements, src.pointer, src.num_elements, access_key, key_source, option);
}
Result DeprecatedService::DecryptAesKey(Out out_key, KeySource key_source, u32 generation, u32 option) {
- return spl::DecryptAesKey(out_key.GetPointer(), key_source, generation, option);
+ return impl::DecryptAesKey(out_key.GetPointer(), key_source, generation, option);
}
Result DeprecatedService::CryptAesCtrDeprecated(OutBuffer out_buf, u32 keyslot, InBuffer in_buf, IvCtr iv_ctr) {
- return spl::CryptAesCtr(out_buf.buffer, out_buf.num_elements, keyslot, this, in_buf.buffer, in_buf.num_elements, iv_ctr);
+ return impl::CryptAesCtr(out_buf.buffer, out_buf.num_elements, keyslot, this, in_buf.buffer, in_buf.num_elements, iv_ctr);
}
Result DeprecatedService::CryptAesCtr(OutBuffer out_buf, u32 keyslot, InBuffer in_buf, IvCtr iv_ctr) {
- return spl::CryptAesCtr(out_buf.buffer, out_buf.num_elements, keyslot, this, in_buf.buffer, in_buf.num_elements, iv_ctr);
+ return impl::CryptAesCtr(out_buf.buffer, out_buf.num_elements, keyslot, this, in_buf.buffer, in_buf.num_elements, iv_ctr);
}
Result DeprecatedService::ComputeCmac(Out out_cmac, u32 keyslot, InPointer in_buf) {
- return spl::ComputeCmac(out_cmac.GetPointer(), keyslot, this, in_buf.pointer, in_buf.num_elements);
+ return impl::ComputeCmac(out_cmac.GetPointer(), keyslot, this, in_buf.pointer, in_buf.num_elements);
}
Result DeprecatedService::ImportEsKey(InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
- return spl::ImportEsKey(src.pointer, src.num_elements, access_key, key_source, option);
+ return impl::ImportEsKey(src.pointer, src.num_elements, access_key, key_source, option);
}
Result DeprecatedService::UnwrapTitleKey(Out out_access_key, InPointer base, InPointer mod, InPointer label_digest, u32 generation) {
- return spl::UnwrapTitleKey(out_access_key.GetPointer(), base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements, generation);
+ return impl::UnwrapTitleKey(out_access_key.GetPointer(), base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements, generation);
}
Result DeprecatedService::LoadTitleKey(u32 keyslot, AccessKey access_key) {
- return spl::LoadTitleKey(keyslot, this, access_key);
+ return impl::LoadTitleKey(keyslot, this, access_key);
}
Result DeprecatedService::UnwrapCommonTitleKey(Out out_access_key, KeySource key_source, u32 generation) {
- return spl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, generation);
+ return impl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, generation);
}
Result DeprecatedService::AllocateAesKeyslot(Out out_keyslot) {
- return spl::AllocateAesKeyslot(out_keyslot.GetPointer(), this);
+ return impl::AllocateAesKeyslot(out_keyslot.GetPointer(), this);
}
Result DeprecatedService::FreeAesKeyslot(u32 keyslot) {
- return spl::FreeAesKeyslot(keyslot, this);
+ return impl::FreeAesKeyslot(keyslot, this);
}
void DeprecatedService::GetAesKeyslotAvailableEvent(Out out_hnd) {
- out_hnd.SetValue(spl::GetAesKeyslotAvailableEventHandle());
+ out_hnd.SetValue(impl::GetAesKeyslotAvailableEventHandle());
}
Result DeprecatedService::SetBootReason(BootReasonValue boot_reason) {
- return spl::SetBootReason(boot_reason);
+ return impl::SetBootReason(boot_reason);
}
Result DeprecatedService::GetBootReason(Out out) {
- return spl::GetBootReason(out.GetPointer());
+ return impl::GetBootReason(out.GetPointer());
}
}
diff --git a/stratosphere/spl/source/spl_deprecated_service.hpp b/stratosphere/spl/source/spl_deprecated_service.hpp
index d78bb72..ee5e469 100644
--- a/stratosphere/spl/source/spl_deprecated_service.hpp
+++ b/stratosphere/spl/source/spl_deprecated_service.hpp
@@ -17,8 +17,7 @@
#pragma once
#include
#include
-
-#include "spl_types.hpp"
+#include
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_es_service.cpp b/stratosphere/spl/source/spl_es_service.cpp
index 14f4c45..96aa8a1 100644
--- a/stratosphere/spl/source/spl_es_service.cpp
+++ b/stratosphere/spl/source/spl_es_service.cpp
@@ -17,37 +17,37 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_es_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result EsService::ImportEsKey(InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
- return spl::ImportEsKey(src.pointer, src.num_elements, access_key, key_source, option);
+ return impl::ImportEsKey(src.pointer, src.num_elements, access_key, key_source, option);
}
Result EsService::UnwrapTitleKey(Out out_access_key, InPointer base, InPointer mod, InPointer label_digest, u32 generation) {
- return spl::UnwrapTitleKey(out_access_key.GetPointer(), base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements, generation);
+ return impl::UnwrapTitleKey(out_access_key.GetPointer(), base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements, generation);
}
Result EsService::UnwrapCommonTitleKey(Out out_access_key, KeySource key_source, u32 generation) {
- return spl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, generation);
+ return impl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, generation);
}
Result EsService::ImportDrmKey(InPointer src, AccessKey access_key, KeySource key_source) {
- return spl::ImportDrmKey(src.pointer, src.num_elements, access_key, key_source);
+ return impl::ImportDrmKey(src.pointer, src.num_elements, access_key, key_source);
}
Result EsService::DrmExpMod(OutPointerWithClientSize out, InPointer base, InPointer mod) {
- return spl::DrmExpMod(out.pointer, out.num_elements, base.pointer, base.num_elements, mod.pointer, mod.num_elements);
+ return impl::DrmExpMod(out.pointer, out.num_elements, base.pointer, base.num_elements, mod.pointer, mod.num_elements);
}
Result EsService::UnwrapElicenseKey(Out out_access_key, InPointer base, InPointer mod, InPointer label_digest, u32 generation) {
- return spl::UnwrapElicenseKey(out_access_key.GetPointer(), base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements, generation);
+ return impl::UnwrapElicenseKey(out_access_key.GetPointer(), base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements, generation);
}
Result EsService::LoadElicenseKey(u32 keyslot, AccessKey access_key) {
- return spl::LoadElicenseKey(keyslot, this, access_key);
+ return impl::LoadElicenseKey(keyslot, this, access_key);
}
}
diff --git a/stratosphere/spl/source/spl_es_service.hpp b/stratosphere/spl/source/spl_es_service.hpp
index e9828d4..34564c3 100644
--- a/stratosphere/spl/source/spl_es_service.hpp
+++ b/stratosphere/spl/source/spl_es_service.hpp
@@ -17,8 +17,8 @@
#pragma once
#include
#include
+#include
-#include "spl_types.hpp"
#include "spl_rsa_service.hpp"
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_fs_service.cpp b/stratosphere/spl/source/spl_fs_service.cpp
index 95d75c4..a550bdf 100644
--- a/stratosphere/spl/source/spl_fs_service.cpp
+++ b/stratosphere/spl/source/spl_fs_service.cpp
@@ -17,29 +17,29 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_fs_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result FsService::ImportLotusKey(InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
- return spl::ImportLotusKey(src.pointer, src.num_elements, access_key, key_source, option);
+ return impl::ImportLotusKey(src.pointer, src.num_elements, access_key, key_source, option);
}
Result FsService::DecryptLotusMessage(Out out_size, OutPointerWithClientSize out, InPointer base, InPointer mod, InPointer label_digest) {
- return spl::DecryptLotusMessage(out_size.GetPointer(), out.pointer, out.num_elements, base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements);
+ return impl::DecryptLotusMessage(out_size.GetPointer(), out.pointer, out.num_elements, base.pointer, base.num_elements, mod.pointer, mod.num_elements, label_digest.pointer, label_digest.num_elements);
}
Result FsService::GenerateSpecificAesKey(Out out_key, KeySource key_source, u32 generation, u32 which) {
- return spl::GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
+ return impl::GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
}
Result FsService::LoadTitleKey(u32 keyslot, AccessKey access_key) {
- return spl::LoadTitleKey(keyslot, this, access_key);
+ return impl::LoadTitleKey(keyslot, this, access_key);
}
Result FsService::GetPackage2Hash(OutPointerWithClientSize dst) {
- return spl::GetPackage2Hash(dst.pointer, dst.num_elements);
+ return impl::GetPackage2Hash(dst.pointer, dst.num_elements);
}
}
diff --git a/stratosphere/spl/source/spl_fs_service.hpp b/stratosphere/spl/source/spl_fs_service.hpp
index e19d98c..11ce445 100644
--- a/stratosphere/spl/source/spl_fs_service.hpp
+++ b/stratosphere/spl/source/spl_fs_service.hpp
@@ -17,8 +17,8 @@
#pragma once
#include
#include
+#include
-#include "spl_types.hpp"
#include "spl_crypto_service.hpp"
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_general_service.cpp b/stratosphere/spl/source/spl_general_service.cpp
index 4d1e644..fc70c7a 100644
--- a/stratosphere/spl/source/spl_general_service.cpp
+++ b/stratosphere/spl/source/spl_general_service.cpp
@@ -17,37 +17,37 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_general_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result GeneralService::GetConfig(Out out, u32 which) {
- return spl::GetConfig(out.GetPointer(), static_cast(which));
+ return impl::GetConfig(out.GetPointer(), static_cast(which));
}
Result GeneralService::ExpMod(OutPointerWithClientSize out, InPointer base, InPointer exp, InPointer mod) {
- return spl::ExpMod(out.pointer, out.num_elements, base.pointer, base.num_elements, exp.pointer, exp.num_elements, mod.pointer, mod.num_elements);
+ return impl::ExpMod(out.pointer, out.num_elements, base.pointer, base.num_elements, exp.pointer, exp.num_elements, mod.pointer, mod.num_elements);
}
Result GeneralService::SetConfig(u32 which, u64 value) {
- return spl::SetConfig(static_cast(which), value);
+ return impl::SetConfig(static_cast(which), value);
}
Result GeneralService::GenerateRandomBytes(OutPointerWithClientSize out) {
- return spl::GenerateRandomBytes(out.pointer, out.num_elements);
+ return impl::GenerateRandomBytes(out.pointer, out.num_elements);
}
Result GeneralService::IsDevelopment(Out is_dev) {
- return spl::IsDevelopment(is_dev.GetPointer());
+ return impl::IsDevelopment(is_dev.GetPointer());
}
Result GeneralService::SetBootReason(BootReasonValue boot_reason) {
- return spl::SetBootReason(boot_reason);
+ return impl::SetBootReason(boot_reason);
}
Result GeneralService::GetBootReason(Out out) {
- return spl::GetBootReason(out.GetPointer());
+ return impl::GetBootReason(out.GetPointer());
}
}
diff --git a/stratosphere/spl/source/spl_general_service.hpp b/stratosphere/spl/source/spl_general_service.hpp
index a181d91..d6c2f0a 100644
--- a/stratosphere/spl/source/spl_general_service.hpp
+++ b/stratosphere/spl/source/spl_general_service.hpp
@@ -17,8 +17,7 @@
#pragma once
#include
#include
-
-#include "spl_types.hpp"
+#include
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp
index bceb4cd..93973d8 100644
--- a/stratosphere/spl/source/spl_main.cpp
+++ b/stratosphere/spl/source/spl_main.cpp
@@ -22,6 +22,8 @@
#include
#include
+#include "spl_api_impl.hpp"
+
#include "spl_random_service.hpp"
#include "spl_general_service.hpp"
#include "spl_crypto_service.hpp"
@@ -32,8 +34,6 @@
#include "spl_deprecated_service.hpp"
-#include "spl_api.hpp"
-
extern "C" {
extern u32 __start__;
@@ -91,7 +91,7 @@
int main(int argc, char **argv)
{
/* Initialize global context. */
- sts::spl::Initialize();
+ sts::spl::impl::Initialize();
/* Create server manager. */
static auto s_server_manager = WaitableManager(1);
diff --git a/stratosphere/spl/source/spl_manu_service.cpp b/stratosphere/spl/source/spl_manu_service.cpp
index d7168a6..1ee4bfc 100644
--- a/stratosphere/spl/source/spl_manu_service.cpp
+++ b/stratosphere/spl/source/spl_manu_service.cpp
@@ -17,13 +17,13 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_manu_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result ManuService::ReEncryptRsaPrivateKey(OutPointerWithClientSize out, InPointer src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option) {
- return spl::ReEncryptRsaPrivateKey(out.pointer, out.num_elements, src.pointer, src.num_elements, access_key_dec, source_dec, access_key_enc, source_enc, option);
+ return impl::ReEncryptRsaPrivateKey(out.pointer, out.num_elements, src.pointer, src.num_elements, access_key_dec, source_dec, access_key_enc, source_enc, option);
}
}
diff --git a/stratosphere/spl/source/spl_manu_service.hpp b/stratosphere/spl/source/spl_manu_service.hpp
index 044d8da..3c1c6f9 100644
--- a/stratosphere/spl/source/spl_manu_service.hpp
+++ b/stratosphere/spl/source/spl_manu_service.hpp
@@ -17,8 +17,8 @@
#pragma once
#include
#include
+#include
-#include "spl_types.hpp"
#include "spl_rsa_service.hpp"
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_random_service.cpp b/stratosphere/spl/source/spl_random_service.cpp
index 919112a..9127209 100644
--- a/stratosphere/spl/source/spl_random_service.cpp
+++ b/stratosphere/spl/source/spl_random_service.cpp
@@ -17,13 +17,13 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_random_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result RandomService::GenerateRandomBytes(OutBuffer out) {
- return spl::GenerateRandomBytes(out.buffer, out.num_elements);
+ return impl::GenerateRandomBytes(out.buffer, out.num_elements);
}
}
diff --git a/stratosphere/spl/source/spl_random_service.hpp b/stratosphere/spl/source/spl_random_service.hpp
index 7fc3bf9..e89e92b 100644
--- a/stratosphere/spl/source/spl_random_service.hpp
+++ b/stratosphere/spl/source/spl_random_service.hpp
@@ -17,8 +17,7 @@
#pragma once
#include
#include
-
-#include "spl_types.hpp"
+#include
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_rsa_service.cpp b/stratosphere/spl/source/spl_rsa_service.cpp
index da81ae8..e075fa7 100644
--- a/stratosphere/spl/source/spl_rsa_service.cpp
+++ b/stratosphere/spl/source/spl_rsa_service.cpp
@@ -17,17 +17,17 @@
#include
#include
+#include "spl_api_impl.hpp"
#include "spl_rsa_service.hpp"
-#include "spl_api.hpp"
namespace sts::spl {
Result RsaService::DecryptRsaPrivateKeyDeprecated(OutPointerWithClientSize dst, InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
- return spl::DecryptRsaPrivateKey(dst.pointer, dst.num_elements, src.pointer, src.num_elements, access_key, key_source, option);
+ return impl::DecryptRsaPrivateKey(dst.pointer, dst.num_elements, src.pointer, src.num_elements, access_key, key_source, option);
}
Result RsaService::DecryptRsaPrivateKey(OutPointerWithClientSize dst, InPointer src, AccessKey access_key, KeySource key_source) {
- return spl::DecryptRsaPrivateKey(dst.pointer, dst.num_elements, src.pointer, src.num_elements, access_key, key_source, static_cast(smc::DecryptOrImportMode::DecryptRsaPrivateKey));
+ return impl::DecryptRsaPrivateKey(dst.pointer, dst.num_elements, src.pointer, src.num_elements, access_key, key_source, static_cast(smc::DecryptOrImportMode::DecryptRsaPrivateKey));
}
}
diff --git a/stratosphere/spl/source/spl_rsa_service.hpp b/stratosphere/spl/source/spl_rsa_service.hpp
index f9cd57a..7b0933a 100644
--- a/stratosphere/spl/source/spl_rsa_service.hpp
+++ b/stratosphere/spl/source/spl_rsa_service.hpp
@@ -17,8 +17,8 @@
#pragma once
#include
#include
+#include
-#include "spl_types.hpp"
#include "spl_crypto_service.hpp"
namespace sts::spl {
diff --git a/stratosphere/spl/source/spl_smc.cpp b/stratosphere/spl/source/spl_smc.cpp
deleted file mode 100644
index c969afe..0000000
--- a/stratosphere/spl/source/spl_smc.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-
-#include "spl_smc.hpp"
-
-namespace sts::spl::smc {
-
- Result SetConfig(SplConfigItem which, const u64 *value, size_t num_qwords) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::SetConfig);
- args.X[1] = which;
- args.X[2] = 0;
- for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
- args.X[3 + i] = value[i];
- }
- svcCallSecureMonitor(&args);
-
- return static_cast(args.X[0]);
- }
-
- Result GetConfig(u64 *out, size_t num_qwords, SplConfigItem which) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::GetConfig);
- args.X[1] = which;
- svcCallSecureMonitor(&args);
-
- for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
- out[i] = args.X[1 + i];
- }
- return static_cast(args.X[0]);
- }
-
- Result CheckStatus(Result *out, AsyncOperationKey op) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::CheckStatus);
- args.X[1] = op.value;
- svcCallSecureMonitor(&args);
-
- *out = static_cast(args.X[1]);
- return static_cast(args.X[0]);
- }
-
- Result GetResult(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::GetResult);
- args.X[1] = op.value;
- args.X[2] = reinterpret_cast(out_buf);
- args.X[3] = out_buf_size;
- svcCallSecureMonitor(&args);
-
- *out = static_cast(args.X[1]);
- return static_cast(args.X[0]);
- }
-
- Result ExpMod(AsyncOperationKey *out_op, const void *base, const void *exp, size_t exp_size, const void *mod) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::ExpMod);
- args.X[1] = reinterpret_cast(base);
- args.X[2] = reinterpret_cast(exp);
- args.X[3] = reinterpret_cast(mod);
- args.X[4] = exp_size;
- svcCallSecureMonitor(&args);
-
- out_op->value = args.X[1];
- return static_cast(args.X[0]);
- }
-
- Result GenerateRandomBytes(void *out, size_t size) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::GenerateRandomBytes);
- args.X[1] = size;
- svcCallSecureMonitor(&args);
-
- if (args.X[0] == static_cast(Result::Success) && (size <= sizeof(args) - sizeof(args.X[0]))) {
- std::memcpy(out, &args.X[1], size);
- }
- return static_cast(args.X[0]);
- }
-
- Result GenerateAesKek(AccessKey *out, const KeySource &source, u32 generation, u32 option) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::GenerateAesKek);
- args.X[1] = source.data64[0];
- args.X[2] = source.data64[1];
- args.X[3] = generation;
- args.X[4] = option;
- svcCallSecureMonitor(&args);
-
- out->data64[0] = args.X[1];
- out->data64[1] = args.X[2];
- return static_cast(args.X[0]);
- }
-
- Result LoadAesKey(u32 keyslot, const AccessKey &access_key, const KeySource &source) {
- SecmonArgs args;
-
- args.X[0] = static_cast(FunctionId::LoadAesKey);
- args.X[1] = keyslot;
- args.X[2] = access_key.data64[0];
- args.X[3] = access_key.data64[1];
- args.X[4] = source.data64[0];
- args.X[5] = source.data64[1];
- svcCallSecureMonitor(&args);
-
- return static_cast(args.X[0]);
- }
-
- Result CryptAes(AsyncOperationKey *out_op, u32 mode, const IvCtr &iv_ctr, u32 dst_addr, u32 src_addr, size_t size) {
- SecmonArgs args;
-
- args.X[0] = static_cast