diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp index 7bf99b4c4..1fa653a73 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_manu_service.hpp" extern "C" { extern u32 __start__; @@ -91,6 +92,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 MakeManuService = []() { return std::make_shared(&s_secmon_wrapper); }; int main(int argc, char **argv) { @@ -106,10 +108,13 @@ int main(int argc, char **argv) s_server_manager.AddWaitable(new ServiceServer("csrng", 3)); if (GetRuntimeFirmwareVersion() >= FirmwareVersion_400) { s_server_manager.AddWaitable(new ServiceServer("spl:", 9)); - 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: Other services. */ + 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. */ + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) { + s_server_manager.AddWaitable(new ServiceServer("spl:manu", 1)); + } } else { /* TODO, DeprecatedGeneralService */ } diff --git a/stratosphere/spl/source/spl_manu_service.cpp b/stratosphere/spl/source/spl_manu_service.cpp new file mode 100644 index 000000000..b78b7e192 --- /dev/null +++ b/stratosphere/spl/source/spl_manu_service.cpp @@ -0,0 +1,24 @@ +/* + * 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_manu_service.hpp" + +Result ManuService::ReEncryptRsaPrivateKey(OutPointerWithClientSize out, InPointer src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option) { + return this->GetSecureMonitorWrapper()->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 new file mode 100644 index 000000000..e4e0a87c5 --- /dev/null +++ b/stratosphere/spl/source/spl_manu_service.hpp @@ -0,0 +1,58 @@ +/* + * 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_rsa_service.hpp" + +class ManuService : public RsaService { + public: + ManuService(SecureMonitorWrapper *sw) : RsaService(sw) { + /* ... */ + } + + virtual ~ManuService() { + /* ... */ + } + protected: + /* Actual commands. */ + virtual Result ReEncryptRsaPrivateKey(OutPointerWithClientSize out, InPointer src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + 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_secmon_wrapper.cpp b/stratosphere/spl/source/spl_secmon_wrapper.cpp index f46e5b543..83c220c00 100644 --- a/stratosphere/spl/source/spl_secmon_wrapper.cpp +++ b/stratosphere/spl/source/spl_secmon_wrapper.cpp @@ -558,7 +558,7 @@ Result SecureMonitorWrapper::DecryptRsaPrivateKey(void *dst, size_t dst_size, co Result SecureMonitorWrapper::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]; + u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10]; }; ImportSecureExpModKeyLayout *layout = reinterpret_cast(g_work_buffer); @@ -639,7 +639,7 @@ Result SecureMonitorWrapper::ImportEsKey(const void *src, size_t src_size, const return ImportSecureExpModKey(src, src_size, access_key, key_source, SmcDecryptOrImportMode_ImportEsKey); } else { struct ImportEsKeyLayout { - u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize]; + u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10]; }; ImportEsKeyLayout *layout = reinterpret_cast(g_work_buffer); @@ -734,6 +734,40 @@ Result SecureMonitorWrapper::LoadTitleKey(u32 keyslot, const void *owner, const return ConvertToSplResult(SmcWrapper::LoadTitleKey(keyslot, access_key)); } +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]; + 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)); + + SmcResult smc_res = SmcWrapper::ReEncryptRsaPrivateKey(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option); + if (smc_res == SmcResult_Success) { + size_t copy_size = std::min(dst_size, src_size); + armDCacheFlush(layout, copy_size); + std::memcpy(dst, layout->data, copy_size); + } + + return ConvertToSplResult(smc_res); + +} + Result SecureMonitorWrapper::FreeAesKeyslots(const void *owner) { for (size_t i = 0; i < GetMaxKeyslots(); i++) { if (this->keyslot_owners[i] == owner) { diff --git a/stratosphere/spl/source/spl_secmon_wrapper.hpp b/stratosphere/spl/source/spl_secmon_wrapper.hpp index 3addf70b9..d4e93ecb1 100644 --- a/stratosphere/spl/source/spl_secmon_wrapper.hpp +++ b/stratosphere/spl/source/spl_secmon_wrapper.hpp @@ -95,6 +95,9 @@ class SecureMonitorWrapper { /* FS */ Result LoadTitleKey(u32 keyslot, const void *owner, const AccessKey &access_key); + /* 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();