From 419815e4e4e4b2583719e61dba52b563b9b169ae Mon Sep 17 00:00:00 2001 From: idunoe Date: Mon, 27 Oct 2014 13:17:56 +0800 Subject: [PATCH] PS: Added API --- libctru/include/3ds/services/ps.h | 76 +++++++++++++++++++++++ libctru/source/services/ps.c | 100 ++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 libctru/include/3ds/services/ps.h create mode 100644 libctru/source/services/ps.c diff --git a/libctru/include/3ds/services/ps.h b/libctru/include/3ds/services/ps.h new file mode 100644 index 0000000..29c9d95 --- /dev/null +++ b/libctru/include/3ds/services/ps.h @@ -0,0 +1,76 @@ +#pragma once + +typedef enum +{ + ps_CBC_ENC, + ps_CBC_DEC, + ps_CTR_ENC, + ps_CTR_DEC, + ps_CCM_ENC, + ps_CCM_DEC, +} ps_aes_algo; + +typedef enum +{ + ps_KEYSLOT_0D, + ps_KEYSLOT_2D, + ps_KEYSLOT_31, + ps_KEYSLOT_38, + ps_KEYSLOT_32, + ps_KEYSLOT_39, + ps_KEYSLOT_2E, + ps_KEYSLOT_INVALID, + ps_KEYSLOT_36 +} ps_aes_keytypes; + +/* + Requires access to "ps:ps" service +*/ + +Result psInit(); +Result psExit(); + +/* PS_EncryptDecryptAes() +About: Is an interface for the AES Engine, you can only use predetermined keyslots though. +Note: Does not support AES CCM, see PS_EncryptSignDecryptVerifyAesCcm() + + size size of data + in input buffer ptr + out output buffer ptr + aes_algo AES Algorithm to use, see ps_aes_algo + key_type see ps_aes_keytypes + iv ptr to the CTR/IV (This is updated before returning) +*/ +Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, u32 aes_algo, u32 key_type, u8* iv); + +/* PS_EncryptSignDecryptVerifyAesCcm() +About: Is an interface for the AES Engine (CCM Encrypt/Decrypt only), you can only use predetermined keyslots though. +Note: When encrypting, the output buffer size must include the MAC size, when decrypting, the input buffer size must include MAC size. +MAC: When decrypting, if the MAC is invalid, 0xC9010401 is returned. After encrypting the MAC is located at inputbufptr+(totalassocdata+totaldatasize) + + in input buffer ptr + in_size size of input buffer + out output buffer ptr + out_size size of output buffer + data_len length of data to be crypted + mac_data_len length of data associated with MAC + mac_len length of MAC + aes_algo AES Algorithm to use, see ps_aes_algo + key_type see ps_aes_keytypes + nonce ptr to the nonce +*/ +Result PS_EncryptSignDecryptVerifyAesCcm(u8* in, u32 in_size, u8* out, u32 out_size, u32 data_len, u32 mac_data_len, u32 mac_len, u32 aes_algo, u32 key_type, u8* nonce); + +/* PS_GetLocalFriendCodeSeed() +About: Gets a 64bit console id, it's used for some key slot inits + + seed ptr to where the seed is written to +*/ +Result PS_GetLocalFriendCodeSeed(u64* seed); + +/* PS_GetDeviceId() +About: Gets a 32bit device id, it's used for some key slot inits + + device_id ptr to where the device id is written to +*/ +Result PS_GetDeviceId(u32* device_id); \ No newline at end of file diff --git a/libctru/source/services/ps.c b/libctru/source/services/ps.c new file mode 100644 index 0000000..6ea4fb2 --- /dev/null +++ b/libctru/source/services/ps.c @@ -0,0 +1,100 @@ +#include +#include <3ds.h> + +static Handle psHandle; + +Result psInit() +{ + return srvGetServiceHandle(&psHandle, "ps:ps"); +} + +Result psExit() +{ + return svcCloseHandle(psHandle); +} + +Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, u32 aes_algo, u32 key_type, u8* iv) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + u32 *_iv = (u32*)iv; + + cmdbuf[0] = 0x000401C4; + cmdbuf[1] = size; + cmdbuf[2] = _iv[0]; + cmdbuf[3] = _iv[1]; + cmdbuf[4] = _iv[2]; + cmdbuf[5] = _iv[3]; + cmdbuf[6] = aes_algo; + cmdbuf[7] = key_type; + cmdbuf[8] = (size << 0x8) | 0x4; + cmdbuf[9] = (u32)in; + cmdbuf[10] = (size << 0x8) | 0x14; + cmdbuf[11] = (u32)out; + + if((ret = svcSendSyncRequest(psHandle))!=0)return ret; + + _iv[0] = cmdbuf[2]; + _iv[1] = cmdbuf[3]; + _iv[2] = cmdbuf[4]; + _iv[3] = cmdbuf[5]; + + return (Result)cmdbuf[1]; +} + +Result PS_EncryptSignDecryptVerifyAesCcm(u8* in, u32 in_size, u8* out, u32 out_size, u32 data_len, u32 mac_data_len, u32 mac_len, u32 aes_algo, u32 key_type, u8* nonce) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + u32 *_nonce = (u32*)nonce; + + cmdbuf[0] = 0x00050284; + cmdbuf[1] = in_size; + cmdbuf[2] = out_size; + cmdbuf[3] = mac_data_len; + cmdbuf[4] = data_len; + cmdbuf[5] = mac_len; + cmdbuf[6] = _nonce[0]; + cmdbuf[7] = _nonce[1]; + cmdbuf[8] = _nonce[2]; + cmdbuf[9] = aes_algo; + cmdbuf[10] = key_type; + cmdbuf[8] = (in_size << 0x8) | 0x4; + cmdbuf[9] = (u32)in; + cmdbuf[10] = (out_size << 0x8) | 0x14; + cmdbuf[11] = (u32)out; + + if((ret = svcSendSyncRequest(psHandle))!=0)return ret; + + return (Result)cmdbuf[1]; +} + +Result PS_GetLocalFriendCodeSeed(u64* seed) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x000A0000; + + if((ret = svcSendSyncRequest(psHandle))!=0)return ret; + + *seed = (u64)cmdbuf[2] | (u64)cmdbuf[3] << 32; + + return (Result)cmdbuf[1]; +} + +Result PS_GetDeviceId(u32* device_id) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = 0x000B0000; + + if((ret = svcSendSyncRequest(psHandle))!=0)return ret; + + *device_id = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} \ No newline at end of file