Changes

6,470 bytes added ,  20:34, 19 June 2012
Code to do SSL through IOS
This code allows to follow the process for establishing a connection and communication over SSL (through IOS) described in [[:/dev/net/ssl]].

== ssl.c ==
<source lang="c">
#include <gccore.h>
#include <string.h>
#include "ssl.h"

#define ISALIGNED(x) ((((u32)x)&0x1F)==0)

static char __ssl_fs[] ATTRIBUTE_ALIGN(32) = "/dev/net/ssl";

static s32 __ssl_fd = -1;
static s32 __ssl_hid = -1;

u32 ssl_init(void){

if(__ssl_hid < 0 ) {
__ssl_hid = iosCreateHeap(SSL_HEAP_SIZE);
if(__ssl_hid < 0){
return __ssl_hid;
}
}

return 0;
}

u32 ssl_open(void){

s32 ret;

if (__ssl_fd < 0) {
ret = IOS_Open(__ssl_fs,0);
if(ret<0){
return ret;
}
__ssl_fd = ret;
}

return 0;
}

u32 ssl_close(void){
s32 ret;

if(__ssl_fd < 0){
return 0;
}

ret = IOS_Close(__ssl_fd);

__ssl_fd = -1;

if(ret<0){
return ret;
}

return 0;
}

s32 ssl_new(u8 * CN, u32 ssl_verify_options){

s32 ret;
s32 aContext[8] ATTRIBUTE_ALIGN(32);
u32 aVerify_options[8] ATTRIBUTE_ALIGN(32);

ret = ssl_open();
if(ret){
return ret;
}

aVerify_options[0] = ssl_verify_options;

if(ISALIGNED(CN)){ //Avoid alignment if the input is aligned
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, CN, 0x100);
}else{
u8 *aCN = NULL;

aCN = iosAlloc(__ssl_hid, 0x100);
if (!aCN) {
return IPC_ENOMEM;
}

memcpy(aCN, CN, 0x100);
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, aCN, 0x100);

if(aCN){
iosFree(__ssl_hid, aCN);
}
}

ssl_close();

return (ret ? ret : aContext[0]);
}


s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index){

s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aIndex[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

aSsl_context[0] = ssl_context;
aIndex[0] = index;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETBUILTINCLIENTCERT, "d:dd", aResponse, 32, aSsl_context, 32, aIndex, 32);
ssl_close();

return (ret ? ret : aResponse[0]);
}


s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length){

s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

aSsl_context[0] = ssl_context;

if(ISALIGNED(root)){ //Avoid alignment if the input is aligned
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, root, length);
}else{
u8 *aRoot = NULL;

aRoot = iosAlloc(__ssl_hid, length);
if (!aRoot) {
return IPC_ENOMEM;
}

memcpy(aRoot, root, length);
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aRoot, length);

if(aRoot){
iosFree(__ssl_hid, aRoot);
}
}

ssl_close();

return (ret ? ret : aResponse[0]);
}


s32 ssl_connect(s32 ssl_context, s32 socket){

s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aSocket[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

aSsl_context[0] = ssl_context;
aSocket[0] = socket;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_CONNECT, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aSocket, 0x20);
ssl_close();

return (ret ? ret : aResponse[0]);
}


s32 ssl_handshake( s32 ssl_context ){

s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

aSsl_context[0] = ssl_context;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_HANDSHAKE, "d:d", aResponse, 0x20, aSsl_context, 0x20);
ssl_close();

return (ret ? ret : aResponse[0]);
}


s32 ssl_read(s32 ssl_context, void* buffer, u32 length){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

if(!buffer){
return IPC_EINVAL;
}

u8 *aBuffer = NULL;
aBuffer = iosAlloc(__ssl_hid, length);
if (!aBuffer) {
return IPC_ENOMEM;
}

aSsl_context[0] = ssl_context;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_READ, "dd:d", aResponse, 0x20, aBuffer, length, aSsl_context, 0x20);
ssl_close();

if(ret == IPC_OK){
memcpy(buffer, aBuffer, aResponse[0]);
}

if(aBuffer){
iosFree(__ssl_hid, aBuffer);
}

return (ret ? ret : aResponse[0]);
}

s32 ssl_write(s32 ssl_context, const void *buffer, u32 length){

s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

if(!buffer){
return IPC_EINVAL;
}

aSsl_context[0] = ssl_context;

if(ISALIGNED(buffer)){ //Avoid alignment if the input is aligned
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, buffer, length);
}else{
u8 *aBuffer = NULL;
aBuffer = iosAlloc(__ssl_hid, length);
if (!aBuffer) {
return IPC_ENOMEM;
}

memcpy(aBuffer, buffer, length);
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aBuffer, length);
}

ssl_close();

return (ret ? ret : aResponse[0]);
}

s32 ssl_shutdown( s32 ssl_context){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;

ret = ssl_open();
if(ret){
return ret;
}

aSsl_context[0] = ssl_context;

ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SHUTDOWN, "d:d", aResponse, 0x20, aSsl_context, 0x20);

ssl_close();

return (ret ? ret : aResponse[0]);
}
</source>

== ssl.h ==
<source lang="c">
#define IOCTLV_SSL_NEW 1
#define IOCTLV_SSL_CONNECT 2
#define IOCTLV_SSL_HANDSHAKE 3
#define IOCTLV_SSL_READ 4
#define IOCTLV_SSL_WRITE 5
#define IOCTLV_SSL_SHUTDOWN 6
#define IOCTLV_SSL_SETROOTCA 10
#define IOCTLV_SSL_SETBUILTINCLIENTCERT 14

#define SSL_HEAP_SIZE 0xB000

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

u32 ssl_init(void);
u32 ssl_open(void);
u32 ssl_close(void);
s32 ssl_new(u8 * CN, u32 verify_options);
s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index);
s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length);
s32 ssl_connect(s32 ssl_context, s32 socket);
s32 ssl_handshake( s32 ssl_context );
s32 ssl_read(s32 ssl_context, void* buffer, u32 length);
s32 ssl_write(s32 ssl_context, const void * buffer, u32 length);
s32 ssl_shutdown( s32 ssl_context);

#ifdef __cplusplus
}
#endif /* __cplusplus */
</source>
71

edits