diff --git a/nx/include/switch.h b/nx/include/switch.h index e9e63fbf..14259088 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -41,6 +41,7 @@ extern "C" { #include "switch/services/applet.h" #include "switch/services/audin.h" #include "switch/services/audout.h" +#include "switch/services/csrng.h" //#include "switch/services/bsd.h" Use switch/runtime/devices/socket.h instead #include "switch/services/fatal.h" #include "switch/services/time.h" diff --git a/nx/include/switch/services/csrng.h b/nx/include/switch/services/csrng.h new file mode 100644 index 00000000..b97b11b1 --- /dev/null +++ b/nx/include/switch/services/csrng.h @@ -0,0 +1,13 @@ +/** + * @file csrng.h + * @brief Cryptographically-Secure Random Number Generation (csrng) service IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" + +Result csrngInitialize(void); +void csrngExit(void); + +Result csrngGetRandomBytes(void *out, size_t out_size); diff --git a/nx/source/services/csrng.c b/nx/source/services/csrng.c new file mode 100644 index 00000000..38f4a97a --- /dev/null +++ b/nx/source/services/csrng.c @@ -0,0 +1,59 @@ +// Copyright 2018 SciresM +#include +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "kernel/ipc.h" +#include "kernel/detect.h" +#include "services/sm.h" +#include "services/spl.h" + +static Service g_csrngSrv; +static u64 g_csrngRefCnt; + +Result csrngInitialize(void) { + atomicIncrement64(&g_csrngRefCnt); + + if (serviceIsActive(&g_csrngSrv)) + return 0; + + return smGetService(&g_csrngSrv, "csrng"); +} + +void csrngExit(void) { + if (atomicDecrement64(&g_csrngRefCnt) == 0) + serviceClose(&g_csrngSrv); +} + +Result csrngGetRandomBytes(void *out, size_t out_size) { + IpcCommand c; + ipcInitialize(&c); + + ipcAddRecvBuffer(&c, out, out_size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + + Result rc = serviceIpcDispatch(&g_csrngSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +}