diff --git a/libctru/include/3ds/services/httpc.h b/libctru/include/3ds/services/httpc.h index 75866ca..01d2990 100644 --- a/libctru/include/3ds/services/httpc.h +++ b/libctru/include/3ds/services/httpc.h @@ -136,6 +136,37 @@ Result httpcAddTrustedRootCA(httpcContext *context, u8 *cert, u32 certsize); */ Result httpcAddDefaultCert(httpcContext *context, SSLC_DefaultRootCert certID); +/** + * @brief Sets the RootCertChain for a HTTP context. + * @param context Context to use. + * @param RootCertChain_contexthandle Contexthandle for the RootCertChain. + */ +Result httpcSelectRootCertChain(httpcContext *context, u32 RootCertChain_contexthandle); + +/** + * @brief Sets the ClientCert for a HTTP context. + * @param context Context to use. + * @param cert Pointer to DER cert. + * @param certsize Size of the DER cert. + * @param privk Pointer to the DER private key. + * @param privk_size Size of the privk. + */ +Result httpcSetClientCert(httpcContext *context, u8 *cert, u32 certsize, u8 *privk, u32 privk_size); + +/** + * @brief Sets the default clientcert for a HTTP context. + * @param context Context to use. + * @param certID ID of the cert to add, see sslc.h. + */ +Result httpcSetClientCertDefault(httpcContext *context, SSLC_DefaultClientCert certID); + +/** + * @brief Sets the ClientCert contexthandle for a HTTP context. + * @param context Context to use. + * @param ClientCert_contexthandle Contexthandle for the ClientCert. + */ +Result httpcSetClientCertContext(httpcContext *context, u32 ClientCert_contexthandle); + /** * @brief Sets SSL options for the context. * The HTTPC SSL option bits are the same as those defined in sslc.h @@ -144,6 +175,73 @@ Result httpcAddDefaultCert(httpcContext *context, SSLC_DefaultRootCert certID); */ Result httpcSetSSLOpt(httpcContext *context, u32 options); +/** + * @brief Sets the SSL options which will be cleared for the context. + * The HTTPC SSL option bits are the same as those defined in sslc.h + * @param context Context to clear flags on. + * @param options SSL option flags. + */ +Result httpcSetSSLClearOpt(httpcContext *context, u32 options); + +/** + * @brief Creates a RootCertChain. Up to 2 RootCertChains can be created under this user-process. + * @param RootCertChain_contexthandle Output RootCertChain contexthandle. + */ +Result httpcCreateRootCertChain(u32 *RootCertChain_contexthandle); + +/** + * @brief Destroy a RootCertChain. + * @param RootCertChain_contexthandle RootCertChain to use. + */ +Result httpcDestroyRootCertChain(u32 RootCertChain_contexthandle); + +/** + * @brief Adds a RootCA cert to a RootCertChain. + * @param RootCertChain_contexthandle RootCertChain to use. + * @param cert Pointer to DER cert. + * @param certsize Size of the DER cert. + * @param cert_contexthandle Optional output ptr for the cert contexthandle(this can be NULL). + */ +Result httpcRootCertChainAddCert(u32 RootCertChain_contexthandle, u8 *cert, u32 certsize, u32 *cert_contexthandle); + +/** + * @brief Adds a default RootCA cert to a RootCertChain. + * @param RootCertChain_contexthandle RootCertChain to use. + * @param certID ID of the cert to add, see sslc.h. + * @param cert_contexthandle Optional output ptr for the cert contexthandle(this can be NULL). + */ +Result httpcRootCertChainAddDefaultCert(u32 RootCertChain_contexthandle, SSLC_DefaultRootCert certID, u32 *cert_contexthandle); + +/** + * @brief Removes a cert from a RootCertChain. + * @param RootCertChain_contexthandle RootCertChain to use. + * @param cert_contexthandle Contexthandle of the cert to remove. + */ +Result httpcRootCertChainRemoveCert(u32 RootCertChain_contexthandle, u32 cert_contexthandle); + +/** + * @brief Opens a ClientCert-context. Up to 2 ClientCert-contexts can be open under this user-process. + * @param cert Pointer to DER cert. + * @param certsize Size of the DER cert. + * @param privk Pointer to the DER private key. + * @param privk_size Size of the privk. + * @param ClientCert_contexthandle Output ClientCert context handle. + */ +Result httpcOpenClientCertContext(u8 *cert, u32 certsize, u8 *privk, u32 privk_size, u32 *ClientCert_contexthandle); + +/** + * @brief Opens a ClientCert-context with a default clientclient. Up to 2 ClientCert-contexts can be open under this user-process. + * @param certID ID of the cert to add, see sslc.h. + * @param ClientCert_contexthandle Output ClientCert context handle. + */ +Result httpcOpenDefaultClientCertContext(SSLC_DefaultClientCert certID, u32 *ClientCert_contexthandle); + +/** + * @brief Closes a ClientCert context. + * @param ClientCert_contexthandle ClientCert context to use. + */ +Result httpcCloseClientCertContext(u32 ClientCert_contexthandle); + /** * @brief Downloads data from the HTTP context into a buffer. * The *entire* content must be downloaded before using httpcCloseContext(), otherwise httpcCloseContext() will hang. diff --git a/libctru/source/services/httpc.c b/libctru/source/services/httpc.c index 296111b..d5c7a83 100644 --- a/libctru/source/services/httpc.c +++ b/libctru/source/services/httpc.c @@ -433,6 +433,67 @@ Result httpcAddDefaultCert(httpcContext *context, SSLC_DefaultRootCert certID) return cmdbuf[1]; } +Result httpcSelectRootCertChain(httpcContext *context, u32 RootCertChain_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x26,2,0); // 0x260080 + cmdbuf[1]=context->httphandle; + cmdbuf[2]=RootCertChain_contexthandle; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(context->servhandle)))return ret; + + return cmdbuf[1]; +} + +Result httpcSetClientCert(httpcContext *context, u8 *cert, u32 certsize, u8 *privk, u32 privk_size) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x27,3,4); // 0x2700C4 + cmdbuf[1]=context->httphandle; + cmdbuf[2]=certsize; + cmdbuf[3]=privk_size; + cmdbuf[4]=IPC_Desc_Buffer(certsize, IPC_BUFFER_R); + cmdbuf[5]=(u32)cert; + cmdbuf[6]=IPC_Desc_Buffer(privk_size, IPC_BUFFER_R); + cmdbuf[7]=(u32)privk; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(context->servhandle)))return ret; + + return cmdbuf[1]; +} + +Result httpcSetClientCertDefault(httpcContext *context, SSLC_DefaultClientCert certID) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x28,2,0); // 0x280080 + cmdbuf[1]=context->httphandle; + cmdbuf[2]=certID; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(context->servhandle)))return ret; + + return cmdbuf[1]; +} + +Result httpcSetClientCertContext(httpcContext *context, u32 ClientCert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x29,2,0); // 0x290080 + cmdbuf[1]=context->httphandle; + cmdbuf[2]=ClientCert_contexthandle; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(context->servhandle)))return ret; + + return cmdbuf[1]; +} + Result httpcSetSSLOpt(httpcContext *context, u32 options) { u32* cmdbuf=getThreadCommandBuffer(); @@ -446,3 +507,145 @@ Result httpcSetSSLOpt(httpcContext *context, u32 options) return cmdbuf[1]; } + +Result httpcSetSSLClearOpt(httpcContext *context, u32 options) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x2C,2,0); // 0x2C0080 + cmdbuf[1]=context->httphandle; + cmdbuf[2]=options; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(context->servhandle)))return ret; + + return cmdbuf[1]; +} + +Result httpcCreateRootCertChain(u32 *RootCertChain_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x2D,0,0); // 0x2D0000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + ret = cmdbuf[1]; + + if(R_SUCCEEDED(ret) && RootCertChain_contexthandle)*RootCertChain_contexthandle = cmdbuf[2]; + + return ret; +} + +Result httpcDestroyRootCertChain(u32 RootCertChain_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x2E,1,0); // 0x2E0040 + cmdbuf[1]=RootCertChain_contexthandle; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + + return cmdbuf[1]; +} + +Result httpcRootCertChainAddCert(u32 RootCertChain_contexthandle, u8 *cert, u32 certsize, u32 *cert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x2F,2,2); // 0x2F0082 + 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(__httpc_servhandle)))return ret; + ret = cmdbuf[1]; + + if(R_SUCCEEDED(ret) && cert_contexthandle)*cert_contexthandle = cmdbuf[2]; + + return ret; +} + +Result httpcRootCertChainAddDefaultCert(u32 RootCertChain_contexthandle, SSLC_DefaultRootCert certID, u32 *cert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x30,2,0); // 0x300080 + cmdbuf[1]=RootCertChain_contexthandle; + cmdbuf[2]=certID; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + ret = cmdbuf[1]; + + if(R_SUCCEEDED(ret) && cert_contexthandle)*cert_contexthandle = cmdbuf[2]; + + return ret; +} + +Result httpcRootCertChainRemoveCert(u32 RootCertChain_contexthandle, u32 cert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x31,2,0); // 0x310080 + cmdbuf[1]=RootCertChain_contexthandle; + cmdbuf[2]=cert_contexthandle; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + + return cmdbuf[1]; +} + +Result httpcOpenClientCertContext(u8 *cert, u32 certsize, u8 *privk, u32 privk_size, u32 *ClientCert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x32,2,4); // 0x320084 + cmdbuf[1]=certsize; + cmdbuf[2]=privk_size; + cmdbuf[3]=IPC_Desc_Buffer(certsize, IPC_BUFFER_R); + cmdbuf[4]=(u32)cert; + cmdbuf[5]=IPC_Desc_Buffer(privk_size, IPC_BUFFER_R); + cmdbuf[6]=(u32)privk; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + ret = cmdbuf[1]; + + if(R_SUCCEEDED(ret) && ClientCert_contexthandle)*ClientCert_contexthandle = cmdbuf[2]; + + return ret; +} + +Result httpcOpenDefaultClientCertContext(SSLC_DefaultClientCert certID, u32 *ClientCert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x33,1,0); // 0x330040 + cmdbuf[1]=certID; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + ret = cmdbuf[1]; + + if(R_SUCCEEDED(ret) && ClientCert_contexthandle)*ClientCert_contexthandle = cmdbuf[2]; + + return ret; +} + +Result httpcCloseClientCertContext(u32 ClientCert_contexthandle) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x34,1,0); // 0x340040 + cmdbuf[1]=ClientCert_contexthandle; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(__httpc_servhandle)))return ret; + + return cmdbuf[1]; +}