diff --git a/stratosphere/spl/source/spl_fs_service.cpp b/stratosphere/spl/source/spl_fs_service.cpp
new file mode 100644
index 000000000..81dd84f00
--- /dev/null
+++ b/stratosphere/spl/source/spl_fs_service.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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_fs_service.hpp"
+
+Result FsService::ImportLotusKey(InPointer src, AccessKey access_key, KeySource key_source, u32 option) {
+ return ResultSuccess;
+ /* TODO */
+ return ResultKernelConnectionClosed;
+}
+
+Result FsService::DecryptLotusMessage(Out out_size, OutPointerWithClientSize out, InPointer base, InPointer mod, InPointer label_digest) {
+ return ResultSuccess;
+ /* TODO */
+ return ResultKernelConnectionClosed;
+}
+
+Result FsService::GenerateSpecificAesKey(Out out_key, KeySource key_source, u32 generation, u32 which) {
+ return this->GetSecureMonitorWrapper()->GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
+}
+
+Result FsService::LoadTitleKey(u32 keyslot, AccessKey access_key) {
+ return this->GetSecureMonitorWrapper()->LoadTitleKey(keyslot, this, access_key);
+}
+
+Result FsService::GetPackage2Hash(OutPointerWithClientSize dst) {
+ return this->GetSecureMonitorWrapper()->GetPackage2Hash(dst.pointer, dst.num_elements);
+}
diff --git a/stratosphere/spl/source/spl_fs_service.hpp b/stratosphere/spl/source/spl_fs_service.hpp
new file mode 100644
index 000000000..4a7bd4872
--- /dev/null
+++ b/stratosphere/spl/source/spl_fs_service.hpp
@@ -0,0 +1,65 @@
+/*
+ * 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"
+#include "spl_crypto_service.hpp"
+
+class FsService : public CryptoService {
+ public:
+ FsService(SecureMonitorWrapper *sw) : CryptoService(sw) {
+ /* ... */
+ }
+
+ virtual ~FsService() {
+ /* ... */
+ }
+ protected:
+ /* Actual commands. */
+ virtual Result ImportLotusKey(InPointer src, AccessKey access_key, KeySource key_source, u32 option);
+ virtual Result DecryptLotusMessage(Out out_size, OutPointerWithClientSize out, InPointer base, InPointer mod, InPointer label_digest);
+ virtual Result GenerateSpecificAesKey(Out out_key, KeySource key_source, u32 generation, u32 which);
+ virtual Result LoadTitleKey(u32 keyslot, AccessKey access_key);
+ virtual Result GetPackage2Hash(OutPointerWithClientSize dst);
+ public:
+ DEFINE_SERVICE_DISPATCH_TABLE {
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+ MakeServiceCommandMeta(),
+
+ };
+};
diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp
index 1fa653a73..47eec447e 100644
--- a/stratosphere/spl/source/spl_main.cpp
+++ b/stratosphere/spl/source/spl_main.cpp
@@ -27,6 +27,7 @@
#include "spl_crypto_service.hpp"
#include "spl_ssl_service.hpp"
#include "spl_es_service.hpp"
+#include "spl_fs_service.hpp"
#include "spl_manu_service.hpp"
extern "C" {
@@ -92,6 +93,7 @@ static const auto MakeGeneralService = []() { return std::make_shared(&s_secmon_wrapper); };
static const auto MakeSslService = []() { return std::make_shared(&s_secmon_wrapper); };
static const auto MakeEsService = []() { return std::make_shared(&s_secmon_wrapper); };
+static const auto MakeFsService = []() { return std::make_shared(&s_secmon_wrapper); };
static const auto MakeManuService = []() { return std::make_shared(&s_secmon_wrapper); };
int main(int argc, char **argv)
@@ -111,13 +113,15 @@ int main(int argc, char **argv)
s_server_manager.AddWaitable(new ServiceServer("spl:mig", 6));
s_server_manager.AddWaitable(new ServiceServer("spl:ssl", 2));
s_server_manager.AddWaitable(new ServiceServer("spl:es", 2));
- /* TODO: spl:fs. */
+ s_server_manager.AddWaitable(new ServiceServer("spl:fs", 2));
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
s_server_manager.AddWaitable(new ServiceServer("spl:manu", 1));
}
} else {
/* TODO, DeprecatedGeneralService */
}
+
+ RebootToRcm();
/* Loop forever, servicing our services. */
s_server_manager.Process();
diff --git a/stratosphere/spl/source/spl_secmon_wrapper.cpp b/stratosphere/spl/source/spl_secmon_wrapper.cpp
index 83c220c00..1105ab896 100644
--- a/stratosphere/spl/source/spl_secmon_wrapper.cpp
+++ b/stratosphere/spl/source/spl_secmon_wrapper.cpp
@@ -726,6 +726,10 @@ Result SecureMonitorWrapper::LoadElicenseKey(u32 keyslot, const void *owner, con
return LoadTitleKey(keyslot, owner, access_key);
}
+Result SecureMonitorWrapper::GenerateSpecificAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 which) {
+ return ConvertToSplResult(SmcWrapper::GenerateSpecificAesKey(out_key, key_source, generation, which));
+}
+
Result SecureMonitorWrapper::LoadTitleKey(u32 keyslot, const void *owner, const AccessKey &access_key) {
Result rc = ValidateAesKeyslot(keyslot, owner);
if (R_FAILED(rc)) {
@@ -734,6 +738,22 @@ Result SecureMonitorWrapper::LoadTitleKey(u32 keyslot, const void *owner, const
return ConvertToSplResult(SmcWrapper::LoadTitleKey(keyslot, access_key));
}
+Result SecureMonitorWrapper::GetPackage2Hash(void *dst, const size_t size) {
+ u64 hash[4];
+
+ if (size < sizeof(hash)) {
+ return ResultSplInvalidSize;
+ }
+
+ SmcResult smc_res;
+ if ((smc_res = SmcWrapper::GetConfig(hash, 4, SplConfigItem_Package2Hash)) != SmcResult_Success) {
+ return ConvertToSplResult(smc_res);
+ }
+
+ std::memcpy(dst, hash, sizeof(hash));
+ return ResultSuccess;
+}
+
Result SecureMonitorWrapper::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];
diff --git a/stratosphere/spl/source/spl_secmon_wrapper.hpp b/stratosphere/spl/source/spl_secmon_wrapper.hpp
index d4e93ecb1..4ec4e4222 100644
--- a/stratosphere/spl/source/spl_secmon_wrapper.hpp
+++ b/stratosphere/spl/source/spl_secmon_wrapper.hpp
@@ -93,7 +93,9 @@ class SecureMonitorWrapper {
Result LoadElicenseKey(u32 keyslot, const void *owner, const AccessKey &access_key);
/* FS */
+ 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);
diff --git a/stratosphere/spl/source/spl_smc_wrapper.cpp b/stratosphere/spl/source/spl_smc_wrapper.cpp
index 8f39e87ec..5845f37ce 100644
--- a/stratosphere/spl/source/spl_smc_wrapper.cpp
+++ b/stratosphere/spl/source/spl_smc_wrapper.cpp
@@ -168,7 +168,7 @@ SmcResult SmcWrapper::CryptAes(AsyncOperationKey *out_op, u32 mode, const IvCtr
return static_cast(args.X[0]);
}
-SmcResult SmcWrapper::GenerateSpecificAesKey(u64 *out, const KeySource &source, u32 generation, u32 which) {
+SmcResult SmcWrapper::GenerateSpecificAesKey(AesKey *out_key, const KeySource &source, u32 generation, u32 which) {
SecmonArgs args;
args.X[0] = SmcFunctionId_GenerateSpecificAesKey;
@@ -178,6 +178,8 @@ SmcResult SmcWrapper::GenerateSpecificAesKey(u64 *out, const KeySource &source,
args.X[4] = which;
svcCallSecureMonitor(&args);
+ out_key->data64[0] = args.X[1];
+ out_key->data64[1] = args.X[2];
return static_cast(args.X[0]);
}
diff --git a/stratosphere/spl/source/spl_smc_wrapper.hpp b/stratosphere/spl/source/spl_smc_wrapper.hpp
index be7b682d7..ea8798ee5 100644
--- a/stratosphere/spl/source/spl_smc_wrapper.hpp
+++ b/stratosphere/spl/source/spl_smc_wrapper.hpp
@@ -38,7 +38,7 @@ class SmcWrapper {
static SmcResult GenerateAesKek(AccessKey *out, const KeySource &source, u32 generation, u32 option);
static SmcResult LoadAesKey(u32 keyslot, const AccessKey &access_key, const KeySource &source);
static SmcResult CryptAes(AsyncOperationKey *out_op, u32 mode, const IvCtr &iv_ctr, u32 dst_addr, u32 src_addr, size_t size);
- static SmcResult GenerateSpecificAesKey(u64 *out, const KeySource &source, u32 generation, u32 which);
+ static SmcResult GenerateSpecificAesKey(AesKey *out_key, const KeySource &source, u32 generation, u32 which);
static SmcResult ComputeCmac(Cmac *out_mac, u32 keyslot, const void *data, size_t size);
static SmcResult ReEncryptRsaPrivateKey(void *data, size_t size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option);
static SmcResult DecryptOrImportRsaPrivateKey(void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option);