diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 5a1910d..9aba22b 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -40,6 +40,7 @@ extern "C" { #include <3ds/services/hid.h> #include <3ds/services/irrst.h> #include <3ds/services/httpc.h> +#include <3ds/services/sslc.h> #include <3ds/services/ir.h> #include <3ds/services/ns.h> #include <3ds/services/pm.h> diff --git a/libctru/include/3ds/services/sslc.h b/libctru/include/3ds/services/sslc.h new file mode 100644 index 0000000..b603507 --- /dev/null +++ b/libctru/include/3ds/services/sslc.h @@ -0,0 +1,26 @@ +/** + * @file sslc.h + * @brief SSLC(TLS) service. https://3dbrew.org/wiki/SSL_Services + */ +#pragma once + +/// HTTP context. +typedef struct { + Handle servhandle; ///< Service handle. + u32 sslchandle; ///< SSLC handle. +} sslcContext; + +/// Initializes SSLC. Normally session_handle should be 0. When non-zero this will use the specified handle for the main-service-session without using the Initialize command, instead of using srvGetServiceHandle. +Result sslcInit(Handle session_handle); + +/// Exits SSLC. +void sslcExit(void); + +/** + * @brief Adds a trusted RootCA cert to a RootCertChain. + * @param RootCertChain_contexthandle RootCertChain to use. + * @param cert Pointer to DER cert. + * @param certsize Size of the DER cert. + */ +Result sslcAddTrustedRootCA(u32 RootCertChain_contexthandle, u8 *cert, u32 certsize); + diff --git a/libctru/source/services/sslc.c b/libctru/source/services/sslc.c new file mode 100644 index 0000000..2fe0044 --- /dev/null +++ b/libctru/source/services/sslc.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include <3ds/types.h> +#include <3ds/result.h> +#include <3ds/svc.h> +#include <3ds/srv.h> +#include <3ds/synchronization.h> +#include <3ds/services/sslc.h> +#include <3ds/ipc.h> + +Handle __sslc_servhandle; +static int __sslc_refcount; + +Result SSLC_Initialize(void); + +Result sslcInit(Handle session_handle) +{ + Result ret=0; + + if (AtomicPostIncrement(&__sslc_refcount)) return 0; + + __sslc_servhandle = session_handle; + + if(__sslc_servhandle==0)ret = srvGetServiceHandle(&__sslc_servhandle, "ssl:C"); + if(session_handle==0 && R_SUCCEEDED(ret))ret = SSLC_Initialize(); + if (R_FAILED(ret)) AtomicDecrement(&__sslc_refcount); + + return ret; +} + +void sslcExit(void) +{ + if (AtomicDecrement(&__sslc_refcount)) return; + + svcCloseHandle(__sslc_servhandle); +} + +Result SSLC_Initialize(void) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x1,0,2); // 0x10002 + cmdbuf[1]=IPC_Desc_CurProcessHandle(); + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__sslc_servhandle)))return ret; + + return cmdbuf[1]; +} + +Result sslcAddTrustedRootCA(u32 RootCertChain_contexthandle, u8 *cert, u32 certsize) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x5,2,2); // 0x50082 + cmdbuf[1]=RootCertChain_contexthandle; + cmdbuf[2]=certsize; + cmdbuf[3]=IPC_Desc_Buffer(certsize, IPC_BUFFER_R); + cmdbuf[4]=(u32)cert; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__sslc_servhandle)))return ret; + + return cmdbuf[1]; +} +