mirror of
https://github.com/Atmosphere-NX/Atmosphere-libs.git
synced 2025-06-29 22:42:40 +02:00
Move spl api/smc impls into libstratosphere
This commit is contained in:
parent
13e3f517cb
commit
ca344e1d19
2
Makefile
2
Makefile
@ -16,7 +16,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
SOURCES := source
|
||||
SOURCES := source source/spl source/spl/smc
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
|
22
include/stratosphere/spl.hpp
Normal file
22
include/stratosphere/spl.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include "spl/spl_types.hpp"
|
||||
#include "spl/spl_api.hpp"
|
||||
#include "spl/smc/spl_smc.hpp"
|
57
include/stratosphere/spl/smc/spl_smc.hpp
Normal file
57
include/stratosphere/spl/smc/spl_smc.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include "../spl_types.hpp"
|
||||
|
||||
namespace sts::spl::smc {
|
||||
|
||||
/* Helpers for converting arguments. */
|
||||
inline u32 GetCryptAesMode(CipherMode mode, u32 keyslot) {
|
||||
return static_cast<u32>((static_cast<u32>(mode) << 4) | (keyslot & 7));
|
||||
}
|
||||
|
||||
inline u32 GetUnwrapEsKeyOption(EsKeyType type, u32 generation) {
|
||||
return static_cast<u32>((static_cast<u32>(type) << 6) | (generation & 0x3F));
|
||||
}
|
||||
|
||||
/* Functions. */
|
||||
Result SetConfig(SplConfigItem which, const u64 *value, size_t num_qwords);
|
||||
Result GetConfig(u64 *out, size_t num_qwords, SplConfigItem which);
|
||||
Result CheckStatus(Result *out, AsyncOperationKey op);
|
||||
Result GetResult(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op);
|
||||
Result ExpMod(AsyncOperationKey *out_op, const void *base, const void *exp, size_t exp_size, const void *mod);
|
||||
Result GenerateRandomBytes(void *out, size_t size);
|
||||
Result GenerateAesKek(AccessKey *out, const KeySource &source, u32 generation, u32 option);
|
||||
Result LoadAesKey(u32 keyslot, const AccessKey &access_key, const KeySource &source);
|
||||
Result CryptAes(AsyncOperationKey *out_op, u32 mode, const IvCtr &iv_ctr, u32 dst_addr, u32 src_addr, size_t size);
|
||||
Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &source, u32 generation, u32 which);
|
||||
Result ComputeCmac(Cmac *out_mac, u32 keyslot, const void *data, size_t size);
|
||||
Result 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);
|
||||
Result DecryptOrImportRsaPrivateKey(void *data, size_t size, const AccessKey &access_key, const KeySource &source, DecryptOrImportMode mode);
|
||||
Result SecureExpMod(AsyncOperationKey *out_op, const void *base, const void *mod, SecureExpModMode mode);
|
||||
Result UnwrapTitleKey(AsyncOperationKey *out_op, const void *base, const void *mod, const void *label_digest, size_t label_digest_size, u32 option);
|
||||
Result LoadTitleKey(u32 keyslot, const AccessKey &access_key);
|
||||
Result UnwrapCommonTitleKey(AccessKey *out, const KeySource &source, u32 generation);
|
||||
|
||||
/* Deprecated functions. */
|
||||
Result ImportEsKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option);
|
||||
Result DecryptRsaPrivateKey(size_t *out_size, void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option);
|
||||
Result ImportSecureExpModKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option);
|
||||
|
||||
}
|
27
include/stratosphere/spl/spl_api.hpp
Normal file
27
include/stratosphere/spl/spl_api.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spl_types.hpp"
|
||||
|
||||
namespace sts::spl {
|
||||
|
||||
HardwareType GetHardwareType();
|
||||
bool IsRecoveryBoot();
|
||||
bool IsMariko();
|
||||
|
||||
}
|
165
include/stratosphere/spl/spl_types.hpp
Normal file
165
include/stratosphere/spl/spl_types.hpp
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include "../results.hpp"
|
||||
|
||||
namespace sts::spl {
|
||||
|
||||
namespace smc {
|
||||
|
||||
enum class FunctionId : u32 {
|
||||
SetConfig = 0xC3000401,
|
||||
GetConfig = 0xC3000002,
|
||||
CheckStatus = 0xC3000003,
|
||||
GetResult = 0xC3000404,
|
||||
ExpMod = 0xC3000E05,
|
||||
GenerateRandomBytes = 0xC3000006,
|
||||
GenerateAesKek = 0xC3000007,
|
||||
LoadAesKey = 0xC3000008,
|
||||
CryptAes = 0xC3000009,
|
||||
GenerateSpecificAesKey = 0xC300000A,
|
||||
ComputeCmac = 0xC300040B,
|
||||
ReEncryptRsaPrivateKey = 0xC300D60C,
|
||||
DecryptOrImportRsaPrivateKey = 0xC300100D,
|
||||
|
||||
SecureExpMod = 0xC300060F,
|
||||
UnwrapTitleKey = 0xC3000610,
|
||||
LoadTitleKey = 0xC3000011,
|
||||
UnwrapCommonTitleKey = 0xC3000012,
|
||||
|
||||
/* Deprecated functions. */
|
||||
ImportEsKey = 0xC300100C,
|
||||
DecryptRsaPrivateKey = 0xC300100D,
|
||||
ImportSecureExpModKey = 0xC300100E,
|
||||
};
|
||||
|
||||
enum class Result {
|
||||
Success = 0,
|
||||
NotImplemented = 1,
|
||||
InvalidArgument = 2,
|
||||
InProgress = 3,
|
||||
NoAsyncOperation = 4,
|
||||
InvalidAsyncOperation = 5,
|
||||
Blacklisted = 6,
|
||||
|
||||
Max = 99,
|
||||
};
|
||||
|
||||
inline ::Result ConvertResult(Result result) {
|
||||
if (result == Result::Success) {
|
||||
return ResultSuccess;
|
||||
}
|
||||
if (result < Result::Max) {
|
||||
return MAKERESULT(Module_Spl, static_cast<u32>(result));
|
||||
}
|
||||
return ResultSplUnknownSmcResult;
|
||||
}
|
||||
|
||||
enum class CipherMode {
|
||||
CbcEncrypt = 0,
|
||||
CbcDecrypt = 1,
|
||||
Ctr = 2,
|
||||
};
|
||||
|
||||
enum class DecryptOrImportMode {
|
||||
DecryptRsaPrivateKey = 0,
|
||||
ImportLotusKey = 1,
|
||||
ImportEsKey = 2,
|
||||
ImportSslKey = 3,
|
||||
ImportDrmKey = 4,
|
||||
};
|
||||
|
||||
enum class SecureExpModMode {
|
||||
Lotus = 0,
|
||||
Ssl = 1,
|
||||
Drm = 2,
|
||||
};
|
||||
|
||||
enum class EsKeyType {
|
||||
TitleKey = 0,
|
||||
ElicenseKey = 1,
|
||||
};
|
||||
|
||||
struct AsyncOperationKey {
|
||||
u64 value;
|
||||
};
|
||||
}
|
||||
|
||||
enum class HardwareType {
|
||||
Icosa = 0,
|
||||
Copper = 1,
|
||||
Hoag = 2,
|
||||
Iowa = 3,
|
||||
};
|
||||
|
||||
struct BootReasonValue {
|
||||
union {
|
||||
struct {
|
||||
u8 power_intr;
|
||||
u8 rtc_intr;
|
||||
u8 nv_erc;
|
||||
u8 boot_reason;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(BootReasonValue) == sizeof(u32), "BootReasonValue definition!");
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct AesKey {
|
||||
union {
|
||||
u8 data[AES_128_KEY_SIZE];
|
||||
u64 data64[AES_128_KEY_SIZE / sizeof(u64)];
|
||||
};
|
||||
};
|
||||
static_assert(alignof(AesKey) == alignof(u8), "AesKey definition!");
|
||||
|
||||
struct IvCtr {
|
||||
union {
|
||||
u8 data[AES_128_KEY_SIZE];
|
||||
u64 data64[AES_128_KEY_SIZE / sizeof(u64)];
|
||||
};
|
||||
};
|
||||
static_assert(alignof(IvCtr) == alignof(u8), "IvCtr definition!");
|
||||
|
||||
struct Cmac {
|
||||
union {
|
||||
u8 data[AES_128_KEY_SIZE];
|
||||
u64 data64[AES_128_KEY_SIZE / sizeof(u64)];
|
||||
};
|
||||
};
|
||||
static_assert(alignof(Cmac) == alignof(u8), "Cmac definition!");
|
||||
|
||||
struct AccessKey {
|
||||
union {
|
||||
u8 data[AES_128_KEY_SIZE];
|
||||
u64 data64[AES_128_KEY_SIZE / sizeof(u64)];
|
||||
};
|
||||
};
|
||||
static_assert(alignof(AccessKey) == alignof(u8), "AccessKey definition!");
|
||||
|
||||
struct KeySource {
|
||||
union {
|
||||
u8 data[AES_128_KEY_SIZE];
|
||||
u64 data64[AES_128_KEY_SIZE / sizeof(u64)];
|
||||
};
|
||||
};
|
||||
static_assert(alignof(AccessKey) == alignof(u8), "KeySource definition!");
|
||||
#pragma pack(pop)
|
||||
|
||||
}
|
312
source/spl/smc/spl_smc.cpp
Normal file
312
source/spl/smc/spl_smc.cpp
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
#include <stratosphere/spl/smc/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<u64>(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<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result GetConfig(u64 *out, size_t num_qwords, SplConfigItem which) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(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<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result CheckStatus(Result *out, AsyncOperationKey op) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::CheckStatus);
|
||||
args.X[1] = op.value;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
*out = static_cast<Result>(args.X[1]);
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result GetResult(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::GetResult);
|
||||
args.X[1] = op.value;
|
||||
args.X[2] = reinterpret_cast<u64>(out_buf);
|
||||
args.X[3] = out_buf_size;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
*out = static_cast<Result>(args.X[1]);
|
||||
return static_cast<Result>(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<u64>(FunctionId::ExpMod);
|
||||
args.X[1] = reinterpret_cast<u64>(base);
|
||||
args.X[2] = reinterpret_cast<u64>(exp);
|
||||
args.X[3] = reinterpret_cast<u64>(mod);
|
||||
args.X[4] = exp_size;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out_op->value = args.X[1];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result GenerateRandomBytes(void *out, size_t size) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::GenerateRandomBytes);
|
||||
args.X[1] = size;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
if (args.X[0] == static_cast<u64>(Result::Success) && (size <= sizeof(args) - sizeof(args.X[0]))) {
|
||||
std::memcpy(out, &args.X[1], size);
|
||||
}
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result GenerateAesKek(AccessKey *out, const KeySource &source, u32 generation, u32 option) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(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<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result LoadAesKey(u32 keyslot, const AccessKey &access_key, const KeySource &source) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(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<Result>(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<u64>(FunctionId::CryptAes);
|
||||
args.X[1] = mode;
|
||||
args.X[2] = iv_ctr.data64[0];
|
||||
args.X[3] = iv_ctr.data64[1];
|
||||
args.X[4] = src_addr;
|
||||
args.X[5] = dst_addr;
|
||||
args.X[6] = size;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out_op->value = args.X[1];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &source, u32 generation, u32 which) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::GenerateSpecificAesKey);
|
||||
args.X[1] = source.data64[0];
|
||||
args.X[2] = source.data64[1];
|
||||
args.X[3] = generation;
|
||||
args.X[4] = which;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out_key->data64[0] = args.X[1];
|
||||
out_key->data64[1] = args.X[2];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result ComputeCmac(Cmac *out_mac, u32 keyslot, const void *data, size_t size) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::ComputeCmac);
|
||||
args.X[1] = keyslot;
|
||||
args.X[2] = reinterpret_cast<u64>(data);
|
||||
args.X[3] = size;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out_mac->data64[0] = args.X[1];
|
||||
out_mac->data64[1] = args.X[2];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result 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) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::ReEncryptRsaPrivateKey);
|
||||
args.X[1] = reinterpret_cast<u64>(&access_key_dec);
|
||||
args.X[2] = reinterpret_cast<u64>(&access_key_enc);
|
||||
args.X[3] = option;
|
||||
args.X[4] = reinterpret_cast<u64>(data);
|
||||
args.X[5] = size;
|
||||
args.X[6] = reinterpret_cast<u64>(&source_dec);
|
||||
args.X[7] = reinterpret_cast<u64>(&source_enc);
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result DecryptOrImportRsaPrivateKey(void *data, size_t size, const AccessKey &access_key, const KeySource &source, DecryptOrImportMode mode) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::DecryptOrImportRsaPrivateKey);
|
||||
args.X[1] = access_key.data64[0];
|
||||
args.X[2] = access_key.data64[1];
|
||||
args.X[3] = static_cast<u32>(mode);
|
||||
args.X[4] = reinterpret_cast<u64>(data);
|
||||
args.X[5] = size;
|
||||
args.X[6] = source.data64[0];
|
||||
args.X[7] = source.data64[1];
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result SecureExpMod(AsyncOperationKey *out_op, const void *base, const void *mod, SecureExpModMode mode) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::SecureExpMod);
|
||||
args.X[1] = reinterpret_cast<u64>(base);
|
||||
args.X[2] = reinterpret_cast<u64>(mod);
|
||||
args.X[3] = static_cast<u32>(mode);
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out_op->value = args.X[1];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result UnwrapTitleKey(AsyncOperationKey *out_op, const void *base, const void *mod, const void *label_digest, size_t label_digest_size, u32 option) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::UnwrapTitleKey);
|
||||
args.X[1] = reinterpret_cast<u64>(base);
|
||||
args.X[2] = reinterpret_cast<u64>(mod);
|
||||
std::memset(&args.X[3], 0, 4 * sizeof(args.X[3]));
|
||||
std::memcpy(&args.X[3], label_digest, std::min(size_t(4 * sizeof(args.X[3])), label_digest_size));
|
||||
args.X[7] = option;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out_op->value = args.X[1];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result LoadTitleKey(u32 keyslot, const AccessKey &access_key) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::LoadTitleKey);
|
||||
args.X[1] = keyslot;
|
||||
args.X[2] = access_key.data64[0];
|
||||
args.X[3] = access_key.data64[1];
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result UnwrapCommonTitleKey(AccessKey *out, const KeySource &source, u32 generation) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::UnwrapCommonTitleKey);
|
||||
args.X[1] = source.data64[0];
|
||||
args.X[2] = source.data64[1];
|
||||
args.X[3] = generation;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
out->data64[0] = args.X[1];
|
||||
out->data64[1] = args.X[2];
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
|
||||
/* Deprecated functions. */
|
||||
Result ImportEsKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::ImportEsKey);
|
||||
args.X[1] = access_key.data64[0];
|
||||
args.X[2] = access_key.data64[1];
|
||||
args.X[3] = option;
|
||||
args.X[4] = reinterpret_cast<u64>(data);
|
||||
args.X[5] = size;
|
||||
args.X[6] = source.data64[0];
|
||||
args.X[7] = source.data64[1];
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result DecryptRsaPrivateKey(size_t *out_size, void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::DecryptRsaPrivateKey);
|
||||
args.X[1] = access_key.data64[0];
|
||||
args.X[2] = access_key.data64[1];
|
||||
args.X[3] = option;
|
||||
args.X[4] = reinterpret_cast<u64>(data);
|
||||
args.X[5] = size;
|
||||
args.X[6] = source.data64[0];
|
||||
args.X[7] = source.data64[1];
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
*out_size = static_cast<size_t>(args.X[1]);
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
Result ImportSecureExpModKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
||||
SecmonArgs args;
|
||||
|
||||
args.X[0] = static_cast<u64>(FunctionId::ImportSecureExpModKey);
|
||||
args.X[1] = access_key.data64[0];
|
||||
args.X[2] = access_key.data64[1];
|
||||
args.X[3] = option;
|
||||
args.X[4] = reinterpret_cast<u64>(data);
|
||||
args.X[5] = size;
|
||||
args.X[6] = source.data64[0];
|
||||
args.X[7] = source.data64[1];
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
return static_cast<Result>(args.X[0]);
|
||||
}
|
||||
|
||||
}
|
48
source/spl/spl_api.cpp
Normal file
48
source/spl/spl_api.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stratosphere.hpp>
|
||||
#include <stratosphere/spl.hpp>
|
||||
|
||||
namespace sts::spl {
|
||||
|
||||
HardwareType GetHardwareType() {
|
||||
u64 out_val = 0;
|
||||
R_ASSERT(splGetConfig(SplConfigItem_HardwareType, &out_val));
|
||||
return static_cast<HardwareType>(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 HardwareType::Icosa:
|
||||
case HardwareType::Copper:
|
||||
return false;
|
||||
case HardwareType::Hoag:
|
||||
case HardwareType::Iowa:
|
||||
return true;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user