From aafbc310c29284cebc3cdb9448c894243919ee14 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 20 Sep 2019 12:17:27 -0700 Subject: [PATCH] spl: update to use new-ipc --- nx/include/switch/services/spl.h | 5 +- nx/source/services/spl.c | 1241 +++++++----------------------- 2 files changed, 275 insertions(+), 971 deletions(-) diff --git a/nx/include/switch/services/spl.h b/nx/include/switch/services/spl.h index 4f897d8e..8ed557c1 100644 --- a/nx/include/switch/services/spl.h +++ b/nx/include/switch/services/spl.h @@ -6,6 +6,7 @@ */ #pragma once #include "../types.h" +#include "../kernel/event.h" #define SPL_RSA_BUFFER_SIZE (0x100) @@ -74,7 +75,7 @@ Result splCryptoCryptAesCtr(const void *input, void *output, size_t size, u32 ke Result splCryptoComputeCmac(const void *input, size_t size, u32 keyslot, void *out_cmac); Result splCryptoLockAesEngine(u32 *out_keyslot); Result splCryptoUnlockAesEngine(u32 keyslot); -Result splCryptoGetSecurityEngineEvent(Handle *out_event); +Result splCryptoGetSecurityEngineEvent(Event *out_event); Result splRsaDecryptPrivateKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version, void *dst, size_t dst_size); @@ -86,6 +87,8 @@ Result splEsUnwrapRsaOaepWrappedTitlekey(const void *rsa_wrapped_titlekey, const Result splEsUnwrapAesWrappedTitlekey(const void *aes_wrapped_titlekey, u32 key_generation, void *out_sealed_titlekey); Result splEsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version); Result splEsSecureExpMod(const void *input, const void *modulus, void *dst); +Result splEsUnwrapElicenseKey(const void *rsa_wrapped_elicense_key, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_elicense_key); +Result splEsLoadElicenseKey(const void *sealed_elicense_key, u32 keyslot); Result splFsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version); Result splFsSecureExpMod(const void *input, const void *modulus, void *dst); diff --git a/nx/source/services/spl.c b/nx/source/services/spl.c index b51168e2..5191d4ce 100644 --- a/nx/source/services/spl.c +++ b/nx/source/services/spl.c @@ -1,31 +1,32 @@ // Copyright 2018 SciresM +#define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "runtime/hosversion.h" -#include "services/sm.h" #include "services/spl.h" +#include "crypto/sha256.h" + +/* Structs used in service implementations. */ +typedef struct SplKey { + u8 key[0x10]; +} SplKey; static Service g_splSrv, g_splCryptoSrv, g_splSslSrv, g_splEsSrv, g_splFsSrv, g_splManuSrv; -static u64 g_splRefCnt, g_splCryptoRefCnt, g_splSslRefCnt, g_splEsRefCnt, g_splFsRefCnt, g_splManuRefCnt; /* Helper prototypes for accessing handles. */ -static Service* _splGetGeneralSrv(void); -static Service* _splGetCryptoSrv(void); -static Service* _splGetRsaSrv(void); - -static Service* _splGetEsSrv(void); -static Service* _splGetFsSrv(void); -static Service* _splGetSslSrv(void); -static Service* _splGetManuSrv(void); +NX_INLINE Service* _splGetGeneralSrv(void); +NX_INLINE Service* _splGetCryptoSrv(void); +NX_INLINE Service* _splGetRsaSrv(void); +NX_INLINE Service* _splGetEsSrv(void); +NX_INLINE Service* _splGetFsSrv(void); +NX_INLINE Service* _splGetSslSrv(void); +NX_INLINE Service* _splGetManuSrv(void); Service* _splGetGeneralSrv(void) { if (hosversionBefore(4,0,0)) { return &g_splSrv; } - + if (serviceIsActive(&g_splSrv)) { return &g_splSrv; } else { @@ -37,7 +38,7 @@ Service* _splGetCryptoSrv(void) { if (hosversionBefore(4,0,0)) { return &g_splSrv; } - + if (serviceIsActive(&g_splManuSrv)) { return &g_splManuSrv; } else if (serviceIsActive(&g_splFsSrv)) { @@ -55,14 +56,14 @@ Service* _splGetRsaSrv(void) { if (hosversionBefore(4,0,0)) { return &g_splSrv; } - + if (serviceIsActive(&g_splFsSrv)) { return &g_splFsSrv; } else if (serviceIsActive(&g_splEsSrv)) { return &g_splEsSrv; } else { return &g_splSslSrv; - } + } } Service* _splGetEsSrv(void) { @@ -81,937 +82,342 @@ Service* _splGetManuSrv(void) { return hosversionAtLeast(4,0,0) ? &g_splManuSrv : &g_splSrv; } -/* There are like six services, so these helpers will initialize/exit the relevant services. */ -static Result _splSrvInitialize(Service* srv, u64 *refcnt, const char *name) { - atomicIncrement64(refcnt); - - if (serviceIsActive(srv)) - return 0; - - return smGetService(srv, name); +/* Initialization. */ +NX_GENERATE_SERVICE_GUARD(spl) +NX_GENERATE_SERVICE_GUARD(splCrypto) +NX_GENERATE_SERVICE_GUARD(splSsl) +NX_GENERATE_SERVICE_GUARD(splEs) +NX_GENERATE_SERVICE_GUARD(splFs) +NX_GENERATE_SERVICE_GUARD(splManu) + +static Result _splInitialize(void) { + return smGetService(&g_splSrv, "spl:"); } -static void _splSrvExit(Service* srv, u64 *refcnt) { - if (atomicDecrement64(refcnt) == 0) - serviceClose(srv); -} - -Result splInitialize(void) { - return _splSrvInitialize(&g_splSrv, &g_splRefCnt, "spl:"); -} - -void splExit(void) { - return _splSrvExit(&g_splSrv, &g_splRefCnt); +static void _splCleanup() { + serviceClose(&g_splSrv); } Service* splGetServiceSession(void) { return _splGetGeneralSrv(); } -Result splCryptoInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splCryptoSrv, &g_splCryptoRefCnt, "spl:mig"); - } else { - return splInitialize(); - } -} - -void splCryptoExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splCryptoSrv, &g_splCryptoRefCnt); - } else { - return splExit(); - } -} - -Service* splCryptoGetServiceSession(void) { - return _splGetCryptoSrv(); -} - -Result splSslInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splSslSrv, &g_splSslRefCnt, "spl:ssl"); - } else { - return splInitialize(); - } -} - -void splSslExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splSslSrv, &g_splSslRefCnt); - } else { - return splExit(); - } -} - -Service* splSslGetServiceSession(void) { - return _splGetSslSrv(); -} - -Result splEsInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splEsSrv, &g_splEsRefCnt, "spl:es"); - } else { - return splInitialize(); - } -} - -void splEsExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splEsSrv, &g_splEsRefCnt); - } else { - return splExit(); - } -} - -Service* splEsGetServiceSession(void) { - return _splGetEsSrv(); -} - -Result splFsInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splFsSrv, &g_splFsRefCnt, "spl:fs"); - } else { - return splInitialize(); - } -} - -void splFsExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splFsSrv, &g_splFsRefCnt); - } else { - return splExit(); - } -} - -Service* splFsGetServiceSession(void) { - return _splGetFsSrv(); -} - -Result splManuInitialize(void) { - return _splSrvInitialize(&g_splManuSrv, &g_splManuRefCnt, "spl:manu"); -} - -void splManuExit(void) { - return _splSrvExit(&g_splManuSrv, &g_splManuRefCnt); -} - -Service* splManuGetServiceSession(void) { - return _splGetManuSrv(); +#define NX_GENERATE_SPL_SRV_INIT(name, subsrv) \ +static Result _spl##name##Initialize(void) { \ + if (hosversionAtLeast(4,0,0)) { \ + return smGetService(&g_spl##name##Srv, "spl:"#subsrv); \ + } else { \ + return splInitialize(); \ + } \ +} \ + \ +static void _spl##name##Cleanup() { \ + if (hosversionAtLeast(4,0,0)) { \ + splExit(); \ + } else { \ + serviceClose(&g_spl##name##Srv); \ + } \ +} \ +Service* _spl##name##GetServiceSession() { \ + return _splGet##name##Srv(); \ } +NX_GENERATE_SPL_SRV_INIT(Crypto, mig) +NX_GENERATE_SPL_SRV_INIT(Ssl, ssl) +NX_GENERATE_SPL_SRV_INIT(Es, es) +NX_GENERATE_SPL_SRV_INIT(Fs, fs) +NX_GENERATE_SPL_SRV_INIT(Manu, manu) /* SPL IGeneralService functionality. */ Result splGetConfig(SplConfigItem config_item, u64 *out_config) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 config_item; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->config_item = config_item; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 out; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *out_config = resp->out; - } - } - - return rc; + } in = { config_item }; + return serviceDispatchInOut(_splGetGeneralSrv(), 0, in, *out_config); } Result splUserExpMod(const void *input, const void *modulus, const void *exp, size_t exp_size, void *dst) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, input, SPL_RSA_BUFFER_SIZE, 0); - ipcAddSendStatic(&c, exp, exp_size, 1); - ipcAddSendStatic(&c, modulus, SPL_RSA_BUFFER_SIZE, 2); - ipcAddRecvStatic(&c, dst, SPL_RSA_BUFFER_SIZE, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(_splGetGeneralSrv(), 1, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { dst, SPL_RSA_BUFFER_SIZE }, + { input, SPL_RSA_BUFFER_SIZE }, + { exp, exp_size }, + { modulus, SPL_RSA_BUFFER_SIZE }, + }, + ); } Result splSetConfig(SplConfigItem config_item, u64 value) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 config_item; u64 value; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->config_item = config_item; - raw->value = value; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { config_item, value }; + return serviceDispatchIn(_splGetGeneralSrv(), 5, in); } Result splGetRandomBytes(void *out, size_t out_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvStatic(&c, out, out_size, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(_splGetGeneralSrv(), 7, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + }, + .buffers = { + { out, out_size }, + }, + ); } Result splIsDevelopment(bool *out_is_development) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 is_development; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *out_is_development = resp->is_development != 0; - } - } - - return rc; + return serviceDispatchOut(_splGetGeneralSrv(), 11, *out_is_development); } Result splSetBootReason(u32 value) { if (hosversionBefore(3,0,0)) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 value; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 24; - raw->value = value; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(_splGetGeneralSrv(), 24, value); } Result splGetBootReason(u32 *out_value) { if (hosversionBefore(3,0,0)) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 25; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 value; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_value = resp->value; - } - } - - return rc; + return serviceDispatchOut(_splGetGeneralSrv(), 25, *out_value); } /* SPL ICryptoService functionality. */ -Result splCryptoGenerateAesKek(const void *wrapped_kek, u32 key_generation, u32 option, void *out_sealed_kek) { - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - u8 wrapped_kek[0x10]; +Result splCryptoGenerateAesKek(const void *wrapped_kek, u32 key_generation, u32 option, void *out_sealed_kek) { + const struct { + SplKey wrapped_kek; u32 key_generation; u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - memcpy(raw->wrapped_kek, wrapped_kek, sizeof(raw->wrapped_kek)); - raw->key_generation = key_generation; - raw->option = option; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_kek[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_kek, resp->sealed_kek, sizeof(resp->sealed_kek)); - } - } - - return rc; + } in = { *((const SplKey *)wrapped_kek), key_generation, option }; + return serviceDispatchInOut(_splGetCryptoSrv(), 2, in, *((SplKey *)out_sealed_kek)); } Result splCryptoLoadAesKey(const void *sealed_kek, const void *wrapped_key, u32 keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; + const struct { + SplKey sealed_kek; + SplKey wrapped_key; u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key), keyslot }; + return serviceDispatchIn(_splGetCryptoSrv(), 3, in); } Result splCryptoGenerateAesKey(const void *sealed_kek, const void *wrapped_key, void *out_sealed_key) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_key[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_key, resp->sealed_key, sizeof(resp->sealed_key)); - } - } - - return rc; + const struct { + SplKey sealed_kek; + SplKey wrapped_key; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key) }; + return serviceDispatchInOut(_splGetCryptoSrv(), 4, in, *((SplKey *)out_sealed_key)); } Result splCryptoDecryptAesKey(const void *wrapped_key, u32 key_generation, u32 option, void *out_sealed_key) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 wrapped_key[0x10]; + const struct { + SplKey wrapped_key; u32 key_generation; u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 14; - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->key_generation = key_generation; - raw->option = option; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_key[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_key, resp->sealed_key, sizeof(resp->sealed_key)); - } - } - - return rc; + } in = { *((const SplKey *)wrapped_key), key_generation, option }; + return serviceDispatchInOut(_splGetCryptoSrv(), 14, in, *((SplKey *)out_sealed_key)); } Result splCryptoCryptAesCtr(const void *input, void *output, size_t size, u32 keyslot, const void *ctr) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, input, size, BufferType_Type1); - ipcAddRecvBuffer(&c, output, size, BufferType_Type1); - - struct { - u64 magic; - u64 cmd_id; - u8 ctr[0x10]; + const struct { + SplKey ctr; u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - memcpy(raw->ctr, ctr, sizeof(raw->ctr)); - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { *((const SplKey *)ctr), keyslot }; + return serviceDispatchIn(_splGetCryptoSrv(), 15, in, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In | SfBufferAttr_HipcMapTransferAllowsNonSecure, + }, + .buffers = { + { output, size }, + { input, size }, + }, + ); } Result splCryptoComputeCmac(const void *input, size_t size, u32 keyslot, void *out_cmac) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, input, size, 0); - - struct { - u64 magic; - u64 cmd_id; - u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 16; - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 cmac[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_cmac, resp->cmac, sizeof(resp->cmac)); - } - } - - return rc; + return serviceDispatchInOut(_splGetCryptoSrv(), 16, keyslot, *((SplKey *)out_cmac), + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { input, size }, + }, + ); } Result splCryptoLockAesEngine(u32 *out_keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 21; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 keyslot; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *out_keyslot = resp->keyslot; - } + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + return serviceDispatchOut(_splGetCryptoSrv(), 21, *out_keyslot); } Result splCryptoUnlockAesEngine(u32 keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 22; - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + return serviceDispatchIn(_splGetCryptoSrv(), 22, keyslot); } -Result splCryptoGetSecurityEngineEvent(Handle *out_event) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 23; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_event = r.Handles[0]; - } +Result splCryptoGetSecurityEngineEvent(Event *out_event) { + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(_splGetCryptoSrv(), 23); + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, true); return rc; } /* SPL IRsaService functionality. NOTE: IRsaService is not a real part of inheritance, unlike ICryptoService/IGeneralService. */ Result splRsaDecryptPrivateKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version, void *dst, size_t dst_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, wrapped_rsa_key, wrapped_rsa_key_size, 0); - ipcAddRecvStatic(&c, dst, dst_size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; - u32 version; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 13; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->version = version; - - Result rc = serviceIpcDispatch(_splGetRsaSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + const struct { + SplKey sealed_kek; + SplKey wrapped_key; + u32 version; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key), version }; + return serviceDispatchIn(_splGetRsaSrv(), 13, in, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { dst, dst_size }, + { wrapped_rsa_key, wrapped_rsa_key_size }, + }, + ); } /* Helper function for RSA key importing. */ -static Result _splImportSecureExpModKey(Service* srv, u64 cmd_id, const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, wrapped_rsa_key, wrapped_rsa_key_size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; - u32 version; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->version = version; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +NX_INLINE Result _splImportSecureExpModKey(Service* srv, u64 cmd_id, const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { + const struct { + SplKey sealed_kek; + SplKey wrapped_key; + u32 version; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key), version }; + return serviceDispatchIn(srv, cmd_id, in, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { wrapped_rsa_key, wrapped_rsa_key_size }, + }, + ); } -static Result _splSecureExpMod(Service* srv, u64 cmd_id, const void *input, const void *modulus, void *dst) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, input, SPL_RSA_BUFFER_SIZE, 0); - ipcAddSendStatic(&c, modulus, SPL_RSA_BUFFER_SIZE, 1); - ipcAddRecvStatic(&c, dst, SPL_RSA_BUFFER_SIZE, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +NX_INLINE Result _splSecureExpMod(Service* srv, u64 cmd_id, const void *input, const void *modulus, void *dst) { + return serviceDispatch(srv, cmd_id, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { dst, SPL_RSA_BUFFER_SIZE }, + { input, SPL_RSA_BUFFER_SIZE }, + { modulus, SPL_RSA_BUFFER_SIZE }, + }, + ); } /* SPL ISslService functionality. */ Result splSslLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splImportSecureExpModKey(&g_splSslSrv, 26, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); } Result splSslSecureExpMod(const void *input, const void *modulus, void *dst) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splSecureExpMod(&g_splSslSrv, 27, input, modulus, dst); } /* SPL IEsService functionality. */ +NX_INLINE Result _splUnwrapRsaOaepWrappedKey(Service *srv, u64 cmd_id, const void *rsa_wrapped_key, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_key) { + return serviceDispatchInOut(srv, cmd_id, key_generation, *((SplKey *)out_sealed_key), + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { rsa_wrapped_key, SPL_RSA_BUFFER_SIZE }, + { modulus, SPL_RSA_BUFFER_SIZE }, + { label_hash, label_hash_size }, + }, + ); +} + +NX_INLINE Result _splLoadContentKey(Service *srv, u64 cmd_id, const void *sealed_key, u32 keyslot) { + const struct { + SplKey sealed_key; + u32 keyslot; + } in = { *((const SplKey *)sealed_key), keyslot }; + return serviceDispatchIn(srv, cmd_id, in); +} + Result splEsLoadRsaOaepKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { return _splImportSecureExpModKey(_splGetEsSrv(), 17, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); } Result splEsUnwrapRsaOaepWrappedTitlekey(const void *rsa_wrapped_titlekey, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_titlekey) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, rsa_wrapped_titlekey, SPL_RSA_BUFFER_SIZE, 0); - ipcAddSendStatic(&c, modulus, SPL_RSA_BUFFER_SIZE, 1); - ipcAddSendStatic(&c, label_hash, label_hash_size, 2); - - struct { - u64 magic; - u64 cmd_id; - u32 key_generation; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 18; - raw->key_generation = key_generation; - - Result rc = serviceIpcDispatch(_splGetEsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_titlekey[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_titlekey, resp->sealed_titlekey, sizeof(resp->sealed_titlekey)); - } - } - - return rc; + return _splUnwrapRsaOaepWrappedKey(_splGetEsSrv(), 18, rsa_wrapped_titlekey, modulus, label_hash, label_hash_size, key_generation, out_sealed_titlekey); } Result splEsUnwrapAesWrappedTitlekey(const void *aes_wrapped_titlekey, u32 key_generation, void *out_sealed_titlekey) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 aes_wrapped_titlekey[0x10]; - u32 key_generation; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 20; - memcpy(raw->aes_wrapped_titlekey, aes_wrapped_titlekey, sizeof(raw->aes_wrapped_titlekey)); - raw->key_generation = key_generation; - - Result rc = serviceIpcDispatch(_splGetEsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_titlekey[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_titlekey, resp->sealed_titlekey, sizeof(resp->sealed_titlekey)); - } + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + const struct { + SplKey aes_wrapped_titlekey; + u32 key_generation; + } in = { *(const SplKey *)aes_wrapped_titlekey, key_generation }; + return serviceDispatchInOut(_splGetEsSrv(), 20, in, *((SplKey *)out_sealed_titlekey)); } Result splEsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splImportSecureExpModKey(&g_splEsSrv, 28, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); } Result splEsSecureExpMod(const void *input, const void *modulus, void *dst) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splSecureExpMod(&g_splEsSrv, 29, input, modulus, dst); } +Result splEsUnwrapElicenseKey(const void *rsa_wrapped_elicense_key, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_elicense_key) { + if (hosversionBefore(6,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + return _splUnwrapRsaOaepWrappedKey(&g_splEsSrv, 31, rsa_wrapped_elicense_key, modulus, label_hash, label_hash_size, key_generation, out_sealed_elicense_key); +} + +Result splEsLoadElicenseKey(const void *sealed_elicense_key, u32 keyslot) { + if (hosversionBefore(6,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + return _splLoadContentKey(&g_splEsSrv, 32, sealed_elicense_key, keyslot); +} + /* SPL IFsService functionality. */ Result splFsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { return _splImportSecureExpModKey(_splGetFsSrv(), 9, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); @@ -1022,157 +428,52 @@ Result splFsSecureExpMod(const void *input, const void *modulus, void *dst) { } Result splFsGenerateSpecificAesKey(const void *wrapped_key, u32 key_generation, u32 option, void *out_sealed_key) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 wrapped_key[0x10]; + const struct { + SplKey wrapped_key; u32 key_generation; u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->key_generation = key_generation; - raw->option = option; - - Result rc = serviceIpcDispatch(_splGetFsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_key[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_key, resp->sealed_key, sizeof(resp->sealed_key)); - } - } - - return rc; + } in = { *((const SplKey *)wrapped_key), key_generation, option }; + return serviceDispatchInOut(_splGetFsSrv(), 12, in, *((SplKey *)out_sealed_key)); } Result splFsLoadTitlekey(const void *sealed_titlekey, u32 keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_titlekey[0x10]; - u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 19; - memcpy(raw->sealed_titlekey, sealed_titlekey, sizeof(raw->sealed_titlekey)); - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetFsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _splLoadContentKey(_splGetFsSrv(), 19, sealed_titlekey, keyslot); } Result splFsGetPackage2Hash(void *out_hash) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 31; - - Result rc = serviceIpcDispatch(&g_splFsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 package2_hash[0x20]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_hash, resp->package2_hash, sizeof(resp->package2_hash)); - } + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + return serviceDispatch(&g_splFsSrv, 31, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + }, + .buffers = { + { out_hash, SHA256_HASH_SIZE }, + }, + ); } /* SPL IManuService funcionality. */ Result splManuEncryptRsaKeyForImport(const void *sealed_kek_pre, const void *wrapped_key_pre, const void *sealed_kek_post, const void *wrapped_kek_post, u32 option, const void *wrapped_rsa_key, void *out_wrapped_rsa_key, size_t rsa_key_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, wrapped_rsa_key, rsa_key_size, 0); - ipcAddRecvStatic(&c, out_wrapped_rsa_key, rsa_key_size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek_pre[0x10]; - u8 wrapped_key_pre[0x10]; - u8 sealed_kek_post[0x10]; - u8 wrapped_kek_post[0x10]; - u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 30; - memcpy(raw->sealed_kek_pre, sealed_kek_pre, sizeof(raw->sealed_kek_pre)); - memcpy(raw->wrapped_key_pre, wrapped_key_pre, sizeof(raw->wrapped_key_pre)); - memcpy(raw->sealed_kek_post, sealed_kek_post, sizeof(raw->sealed_kek_post)); - memcpy(raw->wrapped_kek_post, wrapped_kek_post, sizeof(raw->wrapped_kek_post)); - raw->option = option; - - Result rc = serviceIpcDispatch(&g_splManuSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + const struct { + SplKey sealed_kek_pre; + SplKey wrapped_key_pre; + SplKey sealed_kek_post; + SplKey wrapped_kek_post; + u32 option; + } in = { *((const SplKey *)sealed_kek_pre), *((const SplKey *)wrapped_key_pre), *((const SplKey *)sealed_kek_post), *((const SplKey *)wrapped_kek_post), option }; + return serviceDispatchIn(&g_splManuSrv, 30, in, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { out_wrapped_rsa_key, rsa_key_size }, + { wrapped_rsa_key, rsa_key_size }, + }, + ); }