diff --git a/build/buildtools/commondefs b/build/buildtools/commondefs index d62f196..adb84b2 100644 --- a/build/buildtools/commondefs +++ b/build/buildtools/commondefs @@ -158,6 +158,7 @@ TWL_LIBS_BASE ?= \ libmi \ libvlink \ libctrdg \ + libaes \ ifdef TWL_PROFILE_TYPE TWL_LIBS_BASE += libos.$(TWL_PROFILE_TYPE) @@ -171,6 +172,7 @@ TWL_LIBS_BASE ?= \ libmi_sp \ libvlink_sp \ libnvram_sp \ + libaes_sp \ ifdef TWL_PROFILE_TYPE TWL_LIBS_BASE += libos_sp.$(TWL_PROFILE_TYPE) diff --git a/build/libraries/Makefile b/build/libraries/Makefile index b5d7db6..36d2395 100644 --- a/build/libraries/Makefile +++ b/build/libraries/Makefile @@ -28,6 +28,7 @@ SUBDIRS = \ vlink \ spi \ ctrdg \ + aes \ #---------------------------------------------------------------------------- diff --git a/build/libraries/aes/ARM7/Makefile b/build/libraries/aes/ARM7/Makefile new file mode 100644 index 0000000..f800f8d --- /dev/null +++ b/build/libraries/aes/ARM7/Makefile @@ -0,0 +1,62 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - libraries - aes/ARM7 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +TWL_CODEGEN_ALL ?= True + +# Codegen for sub processer +TWL_PROC = ARM7 + +SRCDIR = ../common . + +SRCS = \ + aes_instruction.c \ + aes_control.c \ + aes_swap.c +# aes_control.c + +TARGET_LIB = libaes_sp$(TWL_LIBSUFFIX).a + + +#---------------------------------------------------------------------------- + +# DEBUG版ビルドの場合、RELEASE版でビルドして +# DEBUG版のライブラリを装います。 + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(TWL_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/aes/ARM7/aes_control.c b/build/libraries/aes/ARM7/aes_control.c new file mode 100644 index 0000000..9cccc6a --- /dev/null +++ b/build/libraries/aes/ARM7/aes_control.c @@ -0,0 +1,483 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes_sp.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +#define AES_PXI_SIZE_CHECK(nums) \ + if (aesWork.total < (nums) && aesWork.total > (nums) + 2) { \ + aesWork.locked = AES_UNLOCKED; \ + AesReturnResult(aesWork.command, AES_PXI_RESULT_INVALID_PARAMETER); \ + break; \ + } + +// アライメント調整してコピーする +#define AES_UNPACK_U32(d, s) \ + (*(d) = (u32)((((u8*)s)[0] << 0) | (((u8*)s)[1] << 8) | (((u8*)s)[2] << 16) | (((u8*)s)[3] << 24))) + +#define AES_UNPACK_U96(d, s) \ + (AES_UNPACK_U32((d)->e + 0, ((u8*)s) + 0), \ + AES_UNPACK_U32((d)->e + 1, ((u8*)s) + 4), \ + AES_UNPACK_U32((d)->e + 2, ((u8*)s) + 8)) + +#define AES_UNPACK_U128(d, s) \ + (AES_UNPACK_U32((d)->e + 0, ((u8*)s) + 0), \ + AES_UNPACK_U32((d)->e + 1, ((u8*)s) + 4), \ + AES_UNPACK_U32((d)->e + 2, ((u8*)s) + 8), \ + AES_UNPACK_U32((d)->e + 3, ((u8*)s) + 12)) + +/*---------------------------------------------------------------------------* + 型定義 + *---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------* + 静的変数定義 + *---------------------------------------------------------------------------*/ +static BOOL aesInitialized; // 初期化確認フラグ +static AESWork aesWork; // ワーク変数をまとめた構造体 + +/*---------------------------------------------------------------------------* + 内部関数定義 + *---------------------------------------------------------------------------*/ +static void AesPxiCallback(PXIFifoTag tag, u32 data, BOOL err); +static void AesReturnResult(u8 command, AESPxiResult result); +static void AesThread(void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_Init + + Description: AESライブラリを初期化する。 + + Arguments: priority + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Init(u32 priority) +{ + // 初期化済みを確認 + if (aesInitialized) + { + return; + } + aesInitialized = 1; + + // 変数初期化 + aesWork.locked = AES_UNLOCKED; + + // PXI関連を初期化 + PXI_Init(); + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_AES, AesPxiCallback); + + // 実処理を行うスレッドを作成 + OS_InitMessageQueue(&aesWork.msgQ, aesWork.msgArray, AES_MESSAGE_ARRAY_MAX); + OS_CreateThread(&aesWork.thread, + AesThread, + 0, + (void *)(aesWork.stack + (AES_THREAD_STACK_SIZE / sizeof(u64))), + AES_THREAD_STACK_SIZE, priority); + OS_WakeupThreadDirect(&aesWork.thread); +} + +/*---------------------------------------------------------------------------* + Name: AES_Lock + + Description: AESライブラリをARM9から使われないようにする。 + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Lock(void) +{ + OSIntrMode enabled; + while (TRUE) + { + enabled = OS_DisableInterrupts(); + if (aesWork.locked == AES_UNLOCKED) + { + aesWork.locked = AES_LOCKED_BY_ARM7; + (void)OS_RestoreInterrupts(enabled); + return; + } + (void)OS_RestoreInterrupts(enabled); + } +} + +/*---------------------------------------------------------------------------* + Name: AES_TryLock + + Description: AESライブラリをARM9から使われないように試みる。 + + Arguments: None. + + Returns: BOOL - ロックできた場合はTRUEを返す + *---------------------------------------------------------------------------*/ +BOOL AES_TryLock(void) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + if (aesWork.locked == AES_UNLOCKED) + { + aesWork.locked = AES_LOCKED_BY_ARM7; + (void)OS_RestoreInterrupts(enabled); + return TRUE; + } + (void)OS_RestoreInterrupts(enabled); + return FALSE; +} + +/*---------------------------------------------------------------------------* + Name: AES_Unlock + + Description: AESライブラリのARM7側のロックを解除する + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Unlock(void) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + if (aesWork.locked == AES_LOCKED_BY_ARM7) { + aesWork.locked = AES_UNLOCKED; + } + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AesPxiCallback + + Description: PXI経由で受信したデータを解析する。 + + Arguments: tag - PXI種別を示すタグ。 + data - 受信したデータ。下位26bitが有効。 + err - PXI通信におけるエラーフラグ。 + ARM9側にて同種別のPXIが初期化されていないことを示す。 + + Returns: None. + *---------------------------------------------------------------------------*/ +static void AesPxiCallback(PXIFifoTag tag, u32 data, BOOL err) +{ +#pragma unused( tag ) + + // PXI通信エラーをチェック + if (err) + { + return; + } + // 先頭データ + if (data & AES_PXI_START_BIT) + { + aesWork.total = (u8)((data & AES_PXI_DATA_NUMS_MASK) >> AES_PXI_DATA_NUMS_SHIFT); + aesWork.current = 0; + aesWork.command = (u8)((data & AES_PXI_COMMAND_MASK) >> AES_PXI_COMMAND_SHIFT); + aesWork.data[aesWork.current++] = (u8)((data & AES_PXI_1ST_DATA_MASK) >> AES_PXI_1ST_DATA_SHIFT); +//OS_TPrintf("START_BIT (total=%d, command=%X).\n", aesWork.total, aesWork.command); + } + // 後続データ + else + { + aesWork.data[aesWork.current++] = (u8)((data & 0xFF0000) >> 16); + aesWork.data[aesWork.current++] = (u8)((data & 0x00FF00) >> 8); + aesWork.data[aesWork.current++] = (u8)((data & 0x0000FF) >> 0); + } + + // パケット完成 + if (aesWork.current >= aesWork.total) // 最大で2つ余分に取得する + { + // 受信したコマンドを解析 + OSIntrMode enabled; + + switch (aesWork.command) + { + // 既知のコマンド群 + case AES_PXI_COMMAND_RESET: + case AES_PXI_COMMAND_IS_BUSY: + case AES_PXI_COMMAND_WAIT: + case AES_PXI_COMMAND_INPUT_FIFO_IS_FULL: + case AES_PXI_COMMAND_OUTPUT_FIFO_IS_EMPTY: + case AES_PXI_COMMAND_WAIT_INPUT_FIFO_NOT_FULL: + case AES_PXI_COMMAND_WAIT_OUTPUT_FIFO_NOT_EMPTY: + case AES_PXI_COMMAND_IS_VALID: + case AES_PXI_COMMAND_SELECT_KEY: + case AES_PXI_COMMAND_SET_KEY: + case AES_PXI_COMMAND_SET_ID: + case AES_PXI_COMMAND_SET_SEED: + case AES_PXI_COMMAND_SET_KEY2: + case AES_PXI_COMMAND_START_CCM_DEC: + case AES_PXI_COMMAND_START_CCM_DEC_NOMAC: + case AES_PXI_COMMAND_START_CCM_ENC: + case AES_PXI_COMMAND_START_CTR: + case AES_PXI_COMMAND_START_DMA_SEND: + case AES_PXI_COMMAND_START_DMA_RECV: + case AES_PXI_COMMAND_CPU_SEND: + case AES_PXI_COMMAND_CPU_RECV: + // スレッドを再開 + if (!OS_SendMessage(&aesWork.msgQ, NULL, OS_MESSAGE_NOBLOCK)) + { + AesReturnResult(aesWork.command, AES_PXI_RESULT_FATAL_ERROR); + } + break; + + // ロック:特殊コマンド (ここで処理する) + case AES_PXI_COMMAND_TRY_LOCK: + enabled = OS_DisableInterrupts(); + if (aesWork.locked == AES_UNLOCKED) + { + // 排他ロック施錠 + aesWork.locked = AES_LOCKED_BY_ARM9; + (void)OS_RestoreInterrupts(enabled); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS_TRUE); + } + else + { + (void)OS_RestoreInterrupts(enabled); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS_FALSE); + } + break; + + // アンロック:特殊コマンド (ここで処理する) + case AES_PXI_COMMAND_UNLOCK: + enabled = OS_DisableInterrupts(); + if (aesWork.locked == AES_LOCKED_BY_ARM9) + { + // 排他ロック開錠 + aesWork.locked = AES_UNLOCKED; + } + (void)OS_RestoreInterrupts(enabled); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); + break; + + // 未知のコマンド + default: + AesReturnResult(aesWork.command, AES_PXI_RESULT_INVALID_COMMAND); + } + } +} + +/*---------------------------------------------------------------------------* + Name: AesReturnResult + + Description: PXI経由で処理結果をARM9に送信する。 + + Arguments: command - 処理したコマンド。 + result - 処理結果。 + + Returns: None. + *---------------------------------------------------------------------------*/ +static void AesReturnResult(u8 command, AESPxiResult result) +{ + while (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_AES, + (u32)(AES_PXI_START_BIT | AES_PXI_RESULT_BIT | + ((command << AES_PXI_COMMAND_SHIFT) & AES_PXI_COMMAND_MASK) + | ((result << AES_PXI_1ST_DATA_SHIFT) & AES_PXI_1ST_DATA_MASK)), + 0)) + { + } +} + +/*---------------------------------------------------------------------------* + Name: AesThread + + Description: AES操作の実処理を行うスレッド。 + + Arguments: arg - 使用しない。 + + Returns: None. + *---------------------------------------------------------------------------*/ +static void AesThread(void *arg) +{ +#pragma unused( arg ) + + OSMessage msg; + BOOL result; + u128 data128a; + u128 data128b; + u96 data96; + u32 data32a; + u32 data32b; + + while (TRUE) + { + // メッセージが発行されるまで寝る + (void)OS_ReceiveMessage(&(aesWork.msgQ), &msg, OS_MESSAGE_BLOCK); + + // コマンドに従って各種処理を実行 + switch (aesWork.command) + { + // AESエンジンのリセット + case AES_PXI_COMMAND_RESET: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_RESET); + AES_Reset(); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + // AESエンジンのビジーチェック + case AES_PXI_COMMAND_IS_BUSY: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_IS_BUSY); + result = AES_IsBusy(); + AesReturnResult(aesWork.command, result ? + AES_PXI_RESULT_SUCCESS_TRUE : AES_PXI_RESULT_SUCCESS_FALSE); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_WAIT: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_WAIT); + AES_Wait(); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_INPUT_FIFO_IS_FULL: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_INPUT_FIFO_IS_FULL); + result = AES_InputFifoIsFull(); + AesReturnResult(aesWork.command, result ? + AES_PXI_RESULT_SUCCESS_TRUE : AES_PXI_RESULT_SUCCESS_FALSE); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_OUTPUT_FIFO_IS_EMPTY: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_OUTPUT_FIFO_IS_EMPTY); + result = AES_OutputFifoIsEmpty(); + AesReturnResult(aesWork.command, result ? + AES_PXI_RESULT_SUCCESS_TRUE : AES_PXI_RESULT_SUCCESS_FALSE); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_WAIT_INPUT_FIFO_NOT_FULL: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_WAIT_INPUT_FIFO_NOT_FULL); + AES_WaitInputFifoNotFull(); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_WAIT_OUTPUT_FIFO_NOT_EMPTY: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_WAIT_OUTPUT_FIFO_NOT_EMPTY); + AES_WaitOutputFifoNotEmpty(); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_IS_VALID: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_IS_VALID); + result = AES_IsValid(); + AesReturnResult(aesWork.command, result ? + AES_PXI_RESULT_SUCCESS_TRUE : AES_PXI_RESULT_SUCCESS_FALSE); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_SELECT_KEY: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_SELECT_KEY); + AES_SelectKey(aesWork.data[0]); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_SET_KEY: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_SET_KEY); + AES_UNPACK_U128(&data128a, &aesWork.data[1]); + AES_SetKey(aesWork.data[0], &data128a); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_SET_ID: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_SET_ID); + AES_UNPACK_U128(&data128a, &aesWork.data[1]); + AES_SetId(aesWork.data[0], &data128a); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_SET_SEED: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_SET_SEED); + AES_UNPACK_U128(&data128a, &aesWork.data[1]); + AES_SetSeed(aesWork.data[0], &data128a); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_SET_KEY2: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_SET_KEY2); + AES_UNPACK_U128(&data128a, &aesWork.data[1]); + AES_UNPACK_U128(&data128b, &aesWork.data[17]); + AES_SetKey2(aesWork.data[1], &data128a, &data128b); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_START_CCM_DEC: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_CCM_DEC); + AES_UNPACK_U96(&data96, &aesWork.data[0]); + AES_UNPACK_U128(&data128a, &aesWork.data[12]); + AES_UNPACK_U32(&data32a, &aesWork.data[28]); + AES_UNPACK_U32(&data32b, &aesWork.data[32]); + AES_StartCcmDec(&data96, &data128a, data32a, data32b, (BOOL)aesWork.data[36]); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_START_CCM_DEC_NOMAC: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_CCM_DEC_NOMAC); + AES_UNPACK_U96(&data96, &aesWork.data[0]); + AES_UNPACK_U32(&data32a, &aesWork.data[12]); + AES_UNPACK_U32(&data32b, &aesWork.data[16]); + AES_StartCcmDec(&data96, NULL, data32a, data32b, (BOOL)aesWork.data[20]); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_START_CCM_ENC: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_CCM_ENC); + AES_UNPACK_U96(&data96, &aesWork.data[0]); + AES_UNPACK_U32(&data32a, &aesWork.data[12]); + AES_UNPACK_U32(&data32b, &aesWork.data[16]); + AES_StartCcmEnc(&data96, data32a, data32b, (BOOL)aesWork.data[20]); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_START_CTR: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_CTR); + AES_UNPACK_U128(&data128a, &aesWork.data[0]); + AES_UNPACK_U32(&data32a, &aesWork.data[16]); + AES_StartCtrDec(&data128a, data32a); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_START_DMA_SEND: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_DMA_SEND); + AES_UNPACK_U32(&data32a, &aesWork.data[1]); + AES_UNPACK_U32(&data32b, &aesWork.data[5]); + AES_DmaSendAsync(aesWork.data[0], (void*)data32a, data32b); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_START_DMA_RECV: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_DMA_RECV); + AES_UNPACK_U32(&data32a, &aesWork.data[1]); + AES_UNPACK_U32(&data32b, &aesWork.data[5]); + AES_DmaRecvAsync(aesWork.data[0], (void*)data32a, data32b); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_CPU_SEND: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_DMA_SEND); + AES_UNPACK_U32(&data32a, &aesWork.data[0]); + AES_UNPACK_U32(&data32b, &aesWork.data[4]); + AES_CpuSend((void*)data32a, data32b); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + case AES_PXI_COMMAND_CPU_RECV: + AES_PXI_SIZE_CHECK(AES_PXI_SIZE_START_DMA_RECV); + AES_UNPACK_U32(&data32a, &aesWork.data[0]); + AES_UNPACK_U32(&data32b, &aesWork.data[4]); + AES_CpuRecv((void*)data32a, data32b); + AesReturnResult(aesWork.command, AES_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達 + break; + + // サポートしないコマンド + default: + AesReturnResult(aesWork.command, AES_PXI_RESULT_INVALID_COMMAND); + } + } +} diff --git a/build/libraries/aes/ARM7/aes_instruction.c b/build/libraries/aes/ARM7/aes_instruction.c new file mode 100644 index 0000000..ecd787a --- /dev/null +++ b/build/libraries/aes/ARM7/aes_instruction.c @@ -0,0 +1,374 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes_common.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +#define reg_AES_NONCE_CTR (*( REGType128v *) REG_AES_NNC_CTR_ADDR) +#define reg_AES_NONCE_CCM (*( REGType96v *) REG_AES_NNC_CTR_ADDR) + +/*---------------------------------------------------------------------------* + 型定義 + *---------------------------------------------------------------------------*/ +typedef struct AESKey +{ + u128 key; + u128 id; + u128 seed; +} +AESKey; + +/*---------------------------------------------------------------------------* + 静的変数定義 + *---------------------------------------------------------------------------*/ +static volatile AESKey *const aesKeyArray = REG_AES_KEY0_ADDR; + +/*---------------------------------------------------------------------------* + 内部関数定義 + *---------------------------------------------------------------------------*/ +static void AES_KeySetup(u32 keyNo); + + +/*---------------------------------------------------------------------------* + Name: AES_Reset + + Description: stop and reset AES block. but key resisters do not clear. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Reset(void) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + reg_AES_AESCNT = REG_AES_AESCNT_OFIFO_CLR_MASK | REG_AES_AESCNT_IFIFO_CLR_MASK; + reg_AES_AESCNT = REG_AES_AESCNT_OFIFO_CLR_MASK | REG_AES_AESCNT_IFIFO_CLR_MASK; + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AES_IsBusy + + Description: check whether AES is busy or not + + Arguments: None. + + Returns: TRUE if AES is busy, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_IsBusy(void) +{ + return (BOOL)((reg_AES_AESCNT & REG_AES_AESCNT_E_MASK) >> REG_AES_AESCNT_E_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: AES_Wait + + Description: wait while AES is busy + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Wait(void) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + while (reg_AES_AESCNT & REG_AES_AESCNT_E_MASK) + { + } + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AES_InputFifoIsFull + + Description: check whether AES input fifo is full or not + + Arguments: None. + + Returns: TRUE if AES is busy, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_InputFifoIsFull(void) +{ + return (((reg_AES_AESCNT & REG_AES_AESCNT_IFIFO_COUNT_MASK) >> REG_AES_AESCNT_IFIFO_COUNT_SHIFT) == 16); +} + +/*---------------------------------------------------------------------------* + Name: AES_OutputFifoIsEmpty + + Description: check whether AES output fifo is empty or not + + Arguments: None. + + Returns: TRUE if AES is busy, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_OutputFifoIsEmpty(void) +{ + return (((reg_AES_AESCNT & REG_AES_AESCNT_OFIFO_COUNT_MASK) >> REG_AES_AESCNT_OFIFO_COUNT_SHIFT) == 0); +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitInputFifoNotFull + + Description: wait while AES input fifo is full. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_WaitInputFifoNotFull(void) +{ + while (((reg_AES_AESCNT & REG_AES_AESCNT_IFIFO_COUNT_MASK) >> REG_AES_AESCNT_IFIFO_COUNT_SHIFT) == 16) + { + } +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitOutputFifoNotEmpty + + Description: wait while AES output fifo is empty. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_WaitOutputFifoNotEmpty(void) +{ + while (((reg_AES_AESCNT & REG_AES_AESCNT_OFIFO_COUNT_MASK) >> REG_AES_AESCNT_OFIFO_COUNT_SHIFT) == 0) + { + } +} + +/*---------------------------------------------------------------------------* + Name: AES_IsValid + + Description: check whether CCM decryption is valid or not. + it may return TRUE just after CCM decryption has been completed. + + Arguments: None. + + Returns: TRUE if CCM decryption was valid, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_IsValid(void) +{ + return (BOOL)((reg_AES_AESCNT & REG_AES_AESCNT_MAC_RSLT_MASK) >> REG_AES_AESCNT_MAC_RSLT_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: AES_SelectKey + + Description: select key from one of four key registers + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + + Arguments: keyNo - key group number. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SelectKey(u32 keyNo) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + AES_ASSERT_KEYNO(keyNo); + while (reg_AES_AESCNT & REG_AES_AESCNT_KEY_BUSY_MASK) + { + } + reg_AES_AESCNT = (reg_AES_AESCNT & ~REG_AES_AESCNT_KEY_SEL_MASK) | + (keyNo << REG_AES_AESCNT_KEY_SEL_SHIFT) | + REG_AES_AESCNT_KEY_SET_MASK; + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AES_SetKey + + Description: set key data into key register + + Arguments: keyNo - key group number. + pKey - pointer to key data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetKey(u32 keyNo, const u128 *pKey) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + vu128 *p = &aesKeyArray[keyNo].key; + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pKey); + *p = *pKey; + (void)OS_RestoreInterrupts(enabled); +} +/*---------------------------------------------------------------------------* + Name: AES_SetId + + Description: set id data into id register + Note: never set key register with id and seed + + Arguments: keyNo - key group number. + pId - pointer to key data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetId(u32 keyNo, const u128 *pId) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + vu128 *p = &aesKeyArray[keyNo].id; + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pId); + *p = *pId; + (void)OS_RestoreInterrupts(enabled); +} +/*---------------------------------------------------------------------------* + Name: AES_SetSeed + + Description: set seed data into seed register + Note: automatically set associated key register with id and seed + + Arguments: keyNo - key group number. + pSeed - pointer to seed data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetSeed(u32 keyNo, const u128 *pSeed) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + vu128 *p = &aesKeyArray[keyNo].seed; + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pSeed); + *p = *pSeed; + (void)OS_RestoreInterrupts(enabled); +} +/*---------------------------------------------------------------------------* + Name: AES_SetKey2 + + Description: set seed/id data into seed/id register + Note: automatically set associated key register with id and seed + + Arguments: keyNo - key group number. + pId - pointer to id data + pSeed - pointer to seed data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetKey2(u32 keyNo, const u128 *pId, const u128 *pSeed) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + vu128 *pI = &aesKeyArray[keyNo].id; + vu128 *pS = &aesKeyArray[keyNo].seed; + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pId); + SDK_NULL_ASSERT(pSeed); + *pI = *pId; + *pS = *pSeed; + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmDec + + Description: start AES engine for AES-CCM decryption. + + Arguments: nonce - pointer to 96-bit nonce data. + mac - pointer to 128-bit mac data. + if NULL, it assumes the mac will be sent from + the input FIFO. + adataLength - length of the associated data. + pdataLength - length of the payload (encrypted) data. + it excludes mac length even if the mac will be + sent from the input FIFO. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_StartCcmDec(const u96 *nonce, const u128 *mac, u32 adataLength, u32 pdataLength, BOOL isDistA) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + AES_ASSERT_DATA_LENGTH(adataLength); + AES_ASSERT_DATA_LENGTH(pdataLength); + SDK_NULL_ASSERT(nonce); + + reg_AES_NONCE_CCM = *nonce; + reg_AES_AES_ASO_LEN = (u16)(adataLength >> 4); + reg_AES_AES_PLD_LEN = (u16)(pdataLength >> 4); + + if (mac) + { + reg_AES_AES_MAC = *mac; + } + reg_AES_AESCNT = AES_INPUT_TYPE_WCNT_4 | AES_OUTPUT_TYPE_WCNT_4 | AES_MAC_LENGTH_16 | + (isDistA ? REG_AES_AESCNT_ADATA_OE_MASK : 0) | + (mac ? REG_AES_AESCNT_MAC_ISEL_MASK : 0) | + REG_AES_AESCNT_I_MASK | REG_AES_AESCNT_E_MASK | AES_MODE_CCM_DECRYPT; + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmEnc + + Description: start AES engine for AES-CCM encryption. + + Arguments: nonce - pointer to 96-bit nonce data. + adataLength - length of the associated data. + pdataLength - length of the payload data. + note that output length will be extended for + the mac data. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_StartCcmEnc(const u96 *nonce, u32 adataLength, u32 pdataLength, BOOL isDistA) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + AES_ASSERT_DATA_LENGTH(adataLength); + AES_ASSERT_DATA_LENGTH(pdataLength); + SDK_NULL_ASSERT(nonce); + + reg_AES_NONCE_CCM = *nonce; + reg_AES_AES_ASO_LEN = (u16)(adataLength >> 4); + reg_AES_AES_PLD_LEN = (u16)(pdataLength >> 4); + + reg_AES_AESCNT = AES_INPUT_TYPE_WCNT_4 | AES_OUTPUT_TYPE_WCNT_4 | AES_MAC_LENGTH_16 | + (isDistA ? REG_AES_AESCNT_ADATA_OE_MASK : 0) | + REG_AES_AESCNT_I_MASK | REG_AES_AESCNT_E_MASK | AES_MODE_CCM_ENCRYPT; + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrDec + + Description: start AES engine for AES-CTR encryption/decryption. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_StartCtrDec(const u128 *iv, u32 length) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + AES_ASSERT_DATA_LENGTH(length); + SDK_NULL_ASSERT(iv); + + reg_AES_NONCE_CTR = *iv; + reg_AES_AES_PLD_LEN = (u16)(length >> 4); + + reg_AES_AESCNT = AES_INPUT_TYPE_WCNT_4 | AES_OUTPUT_TYPE_WCNT_4 | + REG_AES_AESCNT_I_MASK | REG_AES_AESCNT_E_MASK | AES_MODE_CTR; + + (void)OS_RestoreInterrupts(enabled); +} diff --git a/build/libraries/aes/ARM9/Makefile b/build/libraries/aes/ARM9/Makefile new file mode 100644 index 0000000..53d3651 --- /dev/null +++ b/build/libraries/aes/ARM9/Makefile @@ -0,0 +1,56 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - libraries - aes/ARM7 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +TWL_CODEGEN_ALL ?= True + +SRCDIR = ../common . + +SRCS = aes_api.c \ + aes_swap.c + +TARGET_LIB = libaes$(TWL_LIBSUFFIX).a + + +#---------------------------------------------------------------------------- + +# DEBUG版ビルドの場合、RELEASE版でビルドして +# DEBUG版のライブラリを装います。 + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(TWL_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/aes/ARM9/aes_api.c b/build/libraries/aes/ARM9/aes_api.c new file mode 100644 index 0000000..47cde6f --- /dev/null +++ b/build/libraries/aes/ARM9/aes_api.c @@ -0,0 +1,1826 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +// 詰めてコピーする +#define AES_PACK_U32(d, s) \ + ((d)[0] = (u8)((*((u32*)s) >> 0) & 0xFF), \ + (d)[1] = (u8)((*((u32*)s) >> 8) & 0xFF), \ + (d)[2] = (u8)((*((u32*)s) >> 16) & 0xFF), \ + (d)[3] = (u8)((*((u32*)s) >> 24) & 0xFF)) + +#define AES_PACK_U96(d, s) \ + (AES_PACK_U32((d) + 0, ((u96*)s)->e + 0), \ + AES_PACK_U32((d) + 4, ((u96*)s)->e + 1), \ + AES_PACK_U32((d) + 8, ((u96*)s)->e + 2)) + +#define AES_PACK_U128(d, s) \ + (AES_PACK_U32((d) + 0, ((u128*)s)->e + 0), \ + AES_PACK_U32((d) + 4, ((u128*)s)->e + 1), \ + AES_PACK_U32((d) + 8, ((u128*)s)->e + 2), \ + AES_PACK_U32((d) + 12, ((u128*)s)->e + 3)) + +// データ数を設定する +#define AES_SUBSEQUENT_NUMS(a) (((a) << AES_PXI_SUBSEQUENT_NUMS_SHIFT) & AES_PXI_SUBSEQUENT_NUMS_MASK) + +/*---------------------------------------------------------------------------* + 型定義 + *---------------------------------------------------------------------------*/ +typedef struct AESWork +{ + BOOL lock; + AESCallback callback; + AESResult result; + void *callbackArg; +} +AESWork; + +/*---------------------------------------------------------------------------* + 静的変数定義 + *---------------------------------------------------------------------------*/ +static BOOL aesInitialized; +static AESWork aesWork; + +/*---------------------------------------------------------------------------* + 内部関数定義 + *---------------------------------------------------------------------------*/ +static BOOL AesSendPxiCommand(AESPxiCommand command, u8 size, u8 data); +static BOOL AesSendPxiData(u8 *pData); +static void AesPxiCallback(PXIFifoTag tag, u32 data, BOOL err); +static void AesSyncCallback(AESResult result, void *arg); +static void AesCallCallbackAndUnlock(AESResult result); +static void AesWaitBusy(void); + +/*---------------------------------------------------------------------------* + Name: AES_Init + + Description: AESライブラリを初期化する。 + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Init(void) +{ + // 初期化済みを確認 + if (aesInitialized) + { + return; + } + aesInitialized = 1; + + // 変数初期化 + aesWork.lock = FALSE; + aesWork.callback = NULL; + + // PXI関連を初期化 + PXI_Init(); + while (!PXI_IsCallbackReady(PXI_FIFO_TAG_AES, PXI_PROC_ARM7)) + { + } + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_AES, AesPxiCallback); +} + +/*---------------------------------------------------------------------------* + Name: AES_ResetAsync + + Description: stop and reset AES block. but key resisters do not clear. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_ResetAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_RESET; + const u8 size = AES_PXI_SIZE_RESET; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_Reset + + Description: stop and reset AES block. but key resisters do not clear. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_Reset(void) +{ + aesWork.result = AES_ResetAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_IsBusyAsync + + Description: check whether AES is busy or not + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsBusyAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_IS_BUSY; + const u8 size = AES_PXI_SIZE_IS_BUSY; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_IsBusy + + Description: check whether AES is busy or not + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsBusy(void) +{ + aesWork.result = AES_IsBusyAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitAsync + + Description: wait while AES is busy + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_WAIT; + const u8 size = AES_PXI_SIZE_WAIT; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_Wait + + Description: wait while AES is busy + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_Wait(void) +{ + aesWork.result = AES_WaitAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_InputFifoIsFullAsync + + Description: check whether AES input fifo is full or not + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_InputFifoIsFullAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_INPUT_FIFO_IS_FULL; + const u8 size = AES_PXI_SIZE_INPUT_FIFO_IS_FULL; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_InputFifoIsFull + + Description: check whether AES input fifo is full or not + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_InputFifoIsFull(void) +{ + aesWork.result = AES_InputFifoIsFullAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_OutputFifoIsEmptyAsync + + Description: check whether AES output fifo is empty or not + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_OutputFifoIsEmptyAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_OUTPUT_FIFO_IS_EMPTY; + const u8 size = AES_PXI_SIZE_OUTPUT_FIFO_IS_EMPTY; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_OutputFifoIsEmpty + + Description: check whether AES output fifo is empty or not + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_OutputFifoIsEmpty(void) +{ + aesWork.result = AES_OutputFifoIsEmptyAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitInputFifoNotFullAsync + + Description: wait while AES input fifo is full. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitInputFifoNotFullAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_WAIT_INPUT_FIFO_NOT_FULL; + const u8 size = AES_PXI_SIZE_WAIT_INPUT_FIFO_NOT_FULL; + OSIntrMode enabled; + + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitInputFifoNotFull + + Description: wait while AES input fifo is full. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitInputFifoNotFull(void) +{ + aesWork.result = AES_WaitInputFifoNotFullAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitOutputFifoNotEmptyAsync + + Description: wait while AES output fifo is empty. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitOutputFifoNotEmptyAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_WAIT_OUTPUT_FIFO_NOT_EMPTY; + const u8 size = AES_PXI_SIZE_WAIT_OUTPUT_FIFO_NOT_EMPTY; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_WaitOutputFifoNotEmpty + + Description: wait while AES output fifo is empty. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitOutputFifoNotEmpty(void) +{ + aesWork.result = AES_WaitOutputFifoNotEmptyAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_IsValidAsync + + Description: check whether CCM decryption is valid or not. + it may return TRUE just after CCM decryption has been completed. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsValidAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_IS_VALID; + const u8 size = AES_PXI_SIZE_IS_VALID; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_IsValid + + Description: check whether CCM decryption is valid or not. + it may return TRUE just after CCM decryption has been completed. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsValid(void) +{ + aesWork.result = AES_IsValidAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_SelectKeyAsync + + Description: select key from one of four key registers + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + async version + + Arguments: keyNo - key group number. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SelectKeyAsync(u32 keyNo, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_SELECT_KEY; + const u8 size = AES_PXI_SIZE_SELECT_KEY; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, (u8)keyNo) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_SelectKey + + Description: select key from one of four key registers + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + sync version. + + Arguments: keyNo - key group number. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SelectKey(u32 keyNo) +{ + aesWork.result = AES_SelectKeyAsync(keyNo, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetKeyAsync + + Description: set key data into key register + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + async version. + + Arguments: keyNo - key group number. + pKey - pointer to key data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKeyAsync(u32 keyNo, const u128 *pKey, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_SET_KEY; + const u8 size = AES_PXI_SIZE_SET_KEY; + OSIntrMode enabled; + u8 data[size]; + int i; + + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pKey); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + data[0] = (u8)keyNo; + AES_PACK_U128(&data[1], pKey); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetKey + + Description: set key data into key register + sync version. + + Arguments: keyNo - key group number. + pKey - pointer to key data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKey(u32 keyNo, const u128 *pKey) +{ + aesWork.result = AES_SetKeyAsync(keyNo, pKey, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetIdAsync + + Description: set id data into id register + Note: never set key register with id and seed + async version. + + Arguments: keyNo - key group number. + pId - pointer to id data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetIdAsync(u32 keyNo, const u128 *pId, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_SET_ID; + const u8 size = AES_PXI_SIZE_SET_ID; + OSIntrMode enabled; + u8 data[size]; + int i; + + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pId); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + data[0] = (u8)keyNo; + AES_PACK_U128(&data[1], pId); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetId + + Description: set id data into id register + Note: never set key register with id and seed + sync version. + + Arguments: keyNo - key group number. + pId - pointer to id data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetId(u32 keyNo, const u128 *pId) +{ + aesWork.result = AES_SetIdAsync(keyNo, pId, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetSeedAsync + + Description: set id data into id register + Note: automatically set associated key register with id and seed + async version. + + Arguments: keyNo - key group number. + pSeed - pointer to seed data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetSeedAsync(u32 keyNo, const u128 *pSeed, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_SET_SEED; + const u8 size = AES_PXI_SIZE_SET_SEED; + OSIntrMode enabled; + u8 data[size]; + int i; + + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pSeed); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + data[0] = (u8)keyNo; + AES_PACK_U128(&data[1], pSeed); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetSeed + + Description: set id data into id register + Note: automatically set associated key register with id and seed + sync version. + + Arguments: keyNo - key group number. + pSeed - pointer to seed data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetSeed(u32 keyNo, const u128 *pSeed) +{ + aesWork.result = AES_SetSeedAsync(keyNo, pSeed, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetKey2Async + + Description: set seed/id data into seed/id register + Note: automatically set associated key register with id and seed + async version. + + Arguments: keyNo - key group number. + pId - pointer to id data + pSeed - pointer to seed data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKey2Async(u32 keyNo, const u128 *pId, const u128 *pSeed, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_SET_KEY2; + const u8 size = AES_PXI_SIZE_SET_KEY2; + OSIntrMode enabled; + u8 data[size]; + int i; + + AES_ASSERT_KEYNO(keyNo); + SDK_NULL_ASSERT(pId); + SDK_NULL_ASSERT(pSeed); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + data[0] = (u8)keyNo; + AES_PACK_U128(&data[1], pId); + AES_PACK_U128(&data[17], pSeed); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_SetKey2 + + Description: set seed/id data into seed/id register + Note: automatically set associated key register with id and seed + sync version. + + Arguments: keyNo - key group number. + pId - pointer to id data + pSeed - pointer to seed data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKey2(u32 keyNo, const u128 *pId, const u128 *pSeed) +{ + aesWork.result = AES_SetKey2Async(keyNo, pId, pSeed, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmDecAsync + + Description: start AES engine for AES-CCM decryption. + async version. + + Arguments: nonce - pointer to 128-bit nonce data. + mac - pointer to 128-bit mac data. + if NULL, it assumes the mac will be sent from + the input FIFO. + adataLength - length of the associated data. + pdataLength - length of the payload data. + it excludes mac length even if the mac will be + sent from the input FIFO. + isDistA - whether associated data will be output from the + output FIFO or not. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmDecAsync(const u96 *nonce, const u128 *mac, u32 adataLength, u32 pdataLength, BOOL isDistA, AESCallback callback, void *arg) +{ + OSIntrMode enabled; + int i; + + SDK_NULL_ASSERT(nonce); + AES_ASSERT_DATA_LENGTH(adataLength); + AES_ASSERT_DATA_LENGTH(pdataLength); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + if (mac) + { + const AESPxiCommand command = AES_PXI_COMMAND_START_CCM_DEC; + const u8 size = AES_PXI_SIZE_START_CCM_DEC; + u8 data[size]; + + // データ作成 + AES_PACK_U96(&data[0], nonce); + AES_PACK_U128(&data[12], mac); + AES_PACK_U32(&data[28], &adataLength); + AES_PACK_U32(&data[32], &pdataLength); + data[36] = (u8)isDistA; + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + } + else + { + const AESPxiCommand command = AES_PXI_COMMAND_START_CCM_DEC_NOMAC; + const u8 size = AES_PXI_SIZE_START_CCM_DEC_NOMAC; + u8 data[size]; + + // データ作成 + AES_PACK_U96(&data[0], nonce); + AES_PACK_U32(&data[12], &adataLength); + AES_PACK_U32(&data[16], &pdataLength); + data[20] = (u8)isDistA; + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmDec + + Description: start AES engine for AES-CCM decryption. + sync version. + + Arguments: nonce - pointer to 128-bit nonce data. + mac - pointer to 128-bit mac data. + if NULL, it assumes the mac will be sent from + the input FIFO. + adataLength - length of the associated data. + pdataLength - length of the payload data. + it excludes mac length even if the mac will be + sent from the input FIFO. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmDec(const u96 *nonce, const u128 *mac, u32 adataLength, u32 pdataLength, BOOL isDistA) +{ + aesWork.result = AES_StartCcmDecAsync(nonce, mac, adataLength, pdataLength, isDistA, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmEncAsync + + Description: start AES engine for AES-CCM encryption. + async version. + + Arguments: nonce - pointer to 128-bit nonce data. + adataLength - length of the associated data. + pdataLength - length of the payload data. + note that output length will be extended for + the mac data. + isDistA - whether associated data will be output from the + output FIFO or not. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmEncAsync(const u96 *nonce, u32 adataLength, u32 pdataLength, BOOL isDistA, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_START_CCM_ENC; + const u8 size = AES_PXI_SIZE_START_CCM_ENC; + OSIntrMode enabled; + u8 data[size]; + int i; + + SDK_NULL_ASSERT(nonce); + AES_ASSERT_DATA_LENGTH(adataLength); + AES_ASSERT_DATA_LENGTH(pdataLength); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + AES_PACK_U96(&data[0], nonce); + AES_PACK_U32(&data[12], &adataLength); + AES_PACK_U32(&data[16], &pdataLength); + data[20] = (u8)isDistA; + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmEnc + + Description: start AES engine for AES-CCM encryption. + sync version. + + Arguments: nonce - pointer to 128-bit nonce data. + adataLength - length of the associated data. + pdataLength - length of the payload data. + note that output length will be extended for + the mac data. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmEnc(const u96 *nonce, u32 adataLength, u32 pdataLength, BOOL isDistA) +{ + aesWork.result = AES_StartCcmEncAsync(nonce, adataLength, pdataLength, isDistA, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrDecAsync + + Description: start AES engine for AES-CTR encryption/decryption. + async version. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCtrDecAsync(const u128 *iv, u32 length, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_START_CTR; + const u8 size = AES_PXI_SIZE_START_CTR; + OSIntrMode enabled; + u8 data[size]; + int i; + + SDK_NULL_ASSERT(iv); + AES_ASSERT_DATA_LENGTH(length); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + AES_PACK_U128(&data[0], iv); + AES_PACK_U32(&data[16], &length); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrDec + + Description: start AES engine for AES-CTR encryption/decryption. + sync version. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCtrDec(const u128 *iv, u32 length) +{ + aesWork.result = AES_StartCtrDecAsync(iv, length, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaSendAsync + + Description: AES DMA send by AES input FIFO timing. + Should call prior to the AES_Start*(). + async version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + src : source address + length : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaSendAsync(u32 dmaNo, const void *src, u32 length, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_START_DMA_SEND; + const u8 size = AES_PXI_SIZE_START_DMA_SEND; + OSIntrMode enabled; + u8 data[size]; + int i; + + SDK_NULL_ASSERT(iv); + AES_ASSERT_DATA_LENGTH(length); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + data[0] = (u8)dmaNo; + AES_PACK_U32(&data[1], &src); + AES_PACK_U32(&data[5], &length); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaSend + + Description: AES DMA send by AES input FIFO timing. + Should call prior to the AES_Start*(). + sync version. + NOTE: never wait to done to transfer! + + Arguments: dmaNo : DMA channel No. (4 - 7) + src : source address + length : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaSend(u32 dmaNo, const void *src, u32 length) +{ + aesWork.result = AES_StartDmaSendAsync(dmaNo, src, length, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaRecvAsync + + Description: AES DMA receive by AES output FIFO timing. + Should call prior to the AES_Start*(). + async version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + dest : destination address + length : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaRecvAsync(u32 dmaNo, const void *dest, u32 length, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_START_DMA_RECV; + const u8 size = AES_PXI_SIZE_START_DMA_RECV; + OSIntrMode enabled; + u8 data[size]; + int i; + + SDK_NULL_ASSERT(iv); + AES_ASSERT_DATA_LENGTH(length); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + data[0] = (u8)dmaNo; + AES_PACK_U32(&data[1], &dest); + AES_PACK_U32(&data[5], &length); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaRecv + + Description: AES DMA receive by AES output FIFO timing. + Should call prior to the AES_Start*(). + sync version. + NOTE: never wait to done to transfer! + + Arguments: dmaNo : DMA channel No. (4 - 7) + dest : destination address + length : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaRecv(u32 dmaNo, const void *dest, u32 length) +{ + aesWork.result = AES_StartDmaRecvAsync(dmaNo, dest, length, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_CpuSendAsync + + Description: send data to AES input fifo by CPU. + Should call prior to the AES_Start*(). + async version. + NOTE: callback will be called after to done to transfer! + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: src : source address + length : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuSendAsync(const void *src, u32 length, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_CPU_SEND; + const u8 size = AES_PXI_SIZE_CPU_SEND; + OSIntrMode enabled; + u8 data[size]; + int i; + + SDK_NULL_ASSERT(iv); + AES_ASSERT_DATA_LENGTH(length); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + AES_PACK_U32(&data[0], &src); + AES_PACK_U32(&data[4], &length); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_CpuSend + + Description: send data to AES input fifo by CPU. + Should call prior to the AES_Start*(). + sync version. + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: src : source address + length : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuSend(const void *src, u32 length) +{ + aesWork.result = AES_CpuSendAsync(src, length, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_CpuRecvAsync + + Description: receive data from AES input fifo by CPU. + Should call prior to the AES_Start*(). + async version. + NOTE: callback will be called after to done to transfer! + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: dest : destination address + length : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuRecvAsync(const void *dest, u32 length, AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_CPU_RECV; + const u8 size = AES_PXI_SIZE_CPU_RECV; + OSIntrMode enabled; + u8 data[size]; + int i; + + SDK_NULL_ASSERT(iv); + AES_ASSERT_DATA_LENGTH(length); + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + // データ作成 + AES_PACK_U32(&data[0], &dest); + AES_PACK_U32(&data[4], &length); + + // コマンド送信 + if (AesSendPxiCommand(command, size, data[0]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + for (i = 1; i < size; i+=3) { + if (AesSendPxiData(&data[i]) == FALSE) + { + return AES_RESULT_SEND_ERROR; + } + } + + return AES_RESULT_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: AES_CpuRecv + + Description: receive data from AES input fifo by CPU. + Should call prior to the AES_Start*(). + sync version. + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: dest : destination address + length : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuRecv(const void *dest, u32 length) +{ + aesWork.result = AES_CpuRecvAsync(dest, length, AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_TryLockAsync + + Description: AESライブラリをARM7から使われないように試みる。 + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_TryLockAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_TRY_LOCK; + const u8 size = AES_PXI_SIZE_TRY_LOCK; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_TryLock + + Description: AESライブラリをARM7から使われないように試みる。 + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_TryLock(void) +{ + aesWork.result = AES_TryLockAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AES_UnlockAsync + + Description: AESライブラリのARM9側のロックを解除する + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_UnlockAsync(AESCallback callback, void *arg) +{ + const AESPxiCommand command = AES_PXI_COMMAND_UNLOCK; + const u8 size = AES_PXI_SIZE_UNLOCK; + OSIntrMode enabled; + + SDK_NULL_ASSERT(callback); + + enabled = OS_DisableInterrupts(); + if (aesWork.lock) + { + (void)OS_RestoreInterrupts(enabled); + return AES_RESULT_BUSY; + } + aesWork.lock = TRUE; + (void)OS_RestoreInterrupts(enabled); + // コールバック設定 + aesWork.callback = callback; + aesWork.callbackArg = arg; + + return AesSendPxiCommand(command, size, 0) ? AES_RESULT_SUCCESS : AES_RESULT_SEND_ERROR; +} + +/*---------------------------------------------------------------------------* + Name: AES_Unlock + + Description: AESライブラリをARM7から使われないように試みる。 + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_Unlock(void) +{ + aesWork.result = AES_UnlockAsync(AesSyncCallback, 0); + if (aesWork.result == AES_RESULT_SUCCESS) + { + AesWaitBusy(); + } + return aesWork.result; +} + +/*---------------------------------------------------------------------------* + Name: AesSendPxiCommand + + Description: 指定先頭コマンドをPXI経由でARM7に送信する。 + + Arguments: command - 対象コマンド + size - 送信データサイズ (バイト単位) + data - 先頭データ (1バイトのみ) + + Returns: BOOL - PXIに対して送信が完了した場合TRUEを、 + PXIによる送信に失敗した場合FALSEを返す。 + *---------------------------------------------------------------------------*/ +static BOOL AesSendPxiCommand(AESPxiCommand command, u8 size, u8 data) +{ + u32 pxiData = (u32)(AES_PXI_START_BIT | + ((command << AES_PXI_COMMAND_SHIFT) & AES_PXI_COMMAND_MASK) | + ((size << AES_PXI_DATA_NUMS_SHIFT) & AES_PXI_DATA_NUMS_MASK) | + ((data << AES_PXI_1ST_DATA_SHIFT) & AES_PXI_1ST_DATA_MASK)); + if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_AES, pxiData, 0)) + { + return FALSE; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: AesSendPxiData + + Description: 指定後続データをPXI経由でARM7に送信する。 + + Arguments: pData - 3バイトデータの先頭へのポインタ + + Returns: BOOL - PXIに対して送信が完了した場合TRUEを、 + PXIによる送信に失敗した場合FALSEを返す。 + *---------------------------------------------------------------------------*/ +static BOOL AesSendPxiData(u8 *pData) +{ + u32 pxiData = (u32)((pData[0] << 16) | (pData[1] << 8) | pData[2]); + if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_AES, pxiData, 0)) + { + return FALSE; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: AesPxiCallback + + Description: 非同期RTC関数用の共通コールバック関数。 + + Arguments: tag - PXI tag which show message type. + data - message from ARM7. + err - PXI transfer error flag. + + Returns: None. + *---------------------------------------------------------------------------*/ +static void AesPxiCallback(PXIFifoTag tag, u32 data, BOOL err) +{ +#pragma unused( tag ) + AESResult result; + AESPxiResult pxiResult; + u8 command; + + // PXI通信エラーを確認 + if (err) + { + // シーケンスを強制終了 + AesCallCallbackAndUnlock(AES_RESULT_FATAL_ERROR); + return; + } + + // 受信データを解析 + SDK_ASSERT((data & (AES_PXI_START_BIT | AES_PXI_RESULT_BIT)) == (AES_PXI_START_BIT | AES_PXI_RESULT_BIT)); + + command = (u8)((data & AES_PXI_COMMAND_MASK) >> AES_PXI_COMMAND_SHIFT); + pxiResult = (AESPxiResult)((data & AES_PXI_1ST_DATA_MASK) >> AES_PXI_1ST_DATA_SHIFT); + + // 処理結果を確認 + switch (pxiResult) + { + case AES_PXI_RESULT_SUCCESS: + result = AES_RESULT_SUCCESS; + break; + case AES_PXI_RESULT_SUCCESS_TRUE: + result = AES_RESULT_SUCCESS_TRUE; + break; + case AES_PXI_RESULT_SUCCESS_FALSE: + result = AES_RESULT_SUCCESS_FALSE; + break; + case AES_PXI_RESULT_INVALID_COMMAND: + result = AES_RESULT_INVALID_COMMAND; + break; + case AES_PXI_RESULT_INVALID_PARAMETER: + result = AES_RESULT_ILLEGAL_PARAMETER; + break; + case AES_PXI_RESULT_ILLEGAL_STATUS: + result = AES_RESULT_ILLEGAL_STATUS; + break; + case AES_PXI_RESULT_BUSY: + result = AES_RESULT_BUSY; + break; + default: + result = AES_RESULT_FATAL_ERROR; + } + + // コールバックの呼び出し + AesCallCallbackAndUnlock(result); +} + +/*---------------------------------------------------------------------------* + Name: AesSyncCallback + + Description: 同期API用のコールバック + + Arguments: result - ARM7から送られた結果 + arg - 未使用 + + Returns: None. + *---------------------------------------------------------------------------*/ +static void AesSyncCallback(AESResult result, void *arg) +{ +#pragma unused(arg) + aesWork.result = result; +} + +/*---------------------------------------------------------------------------* + Name: AesCallCallbackAndUnlock + + Description: コールバックの呼び出しとロックの解除を行う + + Arguments: result - ARM7から送られた結果 + + Returns: None. + *---------------------------------------------------------------------------*/ +static void AesCallCallbackAndUnlock(AESResult result) +{ + AESCallback cb; + + if (aesWork.lock) + { + aesWork.lock = FALSE; + } + if (aesWork.callback) + { + cb = aesWork.callback; + aesWork.callback = NULL; + cb(result, aesWork.callbackArg); + } +} + +/*---------------------------------------------------------------------------* + Name: AesWaitBusy + + Description: AESの非同期処理がロックされている間待つ。 + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +#if 0 +#include +static asm void AesWaitBusy(void) +{ + ldr r12, =aesWork.lock +loop: + ldr r0, [ r12, #0 ] + cmp r0, #TRUE + beq loop + bx lr +} +#include +#else +extern void PXIi_HandlerRecvFifoNotEmpty(void); +static void AesWaitBusy(void) +{ + volatile BOOL *p = &aesWork.lock; + + while (*p) + { + if (OS_GetCpsrIrq() == OS_INTRMODE_IRQ_DISABLE) + { + PXIi_HandlerRecvFifoNotEmpty(); + } + } +} +#endif diff --git a/build/libraries/aes/Makefile b/build/libraries/aes/Makefile new file mode 100644 index 0000000..59b8458 --- /dev/null +++ b/build/libraries/aes/Makefile @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - libraries - aes +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +ifdef TWL_WITH_ARM7 +SUBDIRS += ARM7 +endif + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/aes/common/aes_swap.c b/build/libraries/aes/common/aes_swap.c new file mode 100644 index 0000000..5e4bb0f --- /dev/null +++ b/build/libraries/aes/common/aes_swap.c @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: swap.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +// +// バイトスワップユーティリティ +// +/*---------------------------------------------------------------------------* + Name: AES_SwapWord128 + + Description: swap 32-bit array to 128-bit little endian. + for example, 0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff + are copied to 0x00112233445566778899aabbccddeeff. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapWord128(u128 *dest, const u32 *src) +{ + int i; + int total = sizeof(u128) / sizeof(u32); + if (dest == NULL || src == NULL) return; + for (i = 0; i < total; i++) { + ((u32*)dest)[i] = src[total - i - 1]; + } +} +/*---------------------------------------------------------------------------* + Name: AES_SwapWord96 + + Description: swap 96-bit array to 128-bit little endian. + for example, 0x00112233, 0x44556677, 0x8899aabb + are copied to 0x00112233445566778899aabb. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapWord96(u96 *dest, const u32 *src) +{ + int i; + int total = sizeof(u96) / sizeof(u32); + if (dest == NULL || src == NULL) return; + for (i = 0; i < total; i++) { + ((u32*)dest)[i] = src[total - i - 1]; + } +} +/*---------------------------------------------------------------------------* + Name: AES_SwapByte128 + + Description: swap 8-bit array to 128-bit little endian. + for example, 0x00, 0x11..., 0xff are copied to + 0x00112233445566778899aabbccddeeff. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapByte128(u128 *dest, const u8 *src) +{ + int i; + int total = sizeof(u128) / sizeof(u8); + if (dest == NULL || src == NULL) return; + for (i = 0; i < total; i++) { + ((u8*)dest)[i] = src[total - i - 1]; + } +} +/*---------------------------------------------------------------------------* + Name: AES_SwapByte96 + + Description: swap 8-bit array to 96-bit little endian. + for example, 0x00, 0x11..., 0xbb are copied to + 0x00112233445566778899aabb. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapByte96(u96 *dest, const u8 *src) +{ + int i; + int total = sizeof(u96) / sizeof(u8); + if (dest == NULL || src == NULL) return; + for (i = 0; i < total; i++) { + ((u8*)dest)[i] = src[total - i - 1]; + } +} diff --git a/build/tests/Makefile b/build/tests/Makefile index bd202f8..10ada14 100644 --- a/build/tests/Makefile +++ b/build/tests/Makefile @@ -20,7 +20,8 @@ include $(TWLSDK_ROOT)/build/buildtools/commondefs #---------------------------------------------------------------------------- -SUBDIRS = os mi +SUBDIRS = os mi \ + aes #---------------------------------------------------------------------------- diff --git a/build/tests/aes/Makefile b/build/tests/aes/Makefile new file mode 100644 index 0000000..417bbda --- /dev/null +++ b/build/tests/aes/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - tests - aes +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = aes-1 _ARM7-aes-1 + + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tests/aes/_ARM7-aes-1/Makefile b/build/tests/aes/_ARM7-aes-1/Makefile new file mode 100644 index 0000000..c2ad9c9 --- /dev/null +++ b/build/tests/aes/_ARM7-aes-1/Makefile @@ -0,0 +1,44 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - OS - demos - _ARM7-aes-1 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +#TWL_CODEGEN = THUMB +TWL_PROC = ARM7 + +TARGET_BIN = main.axf + +SRCS = main.c + +#SRCDIR = # using default +#LCFILE = # using default + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tests/aes/_ARM7-aes-1/src/main.c b/build/tests/aes/_ARM7-aes-1/src/main.c new file mode 100644 index 0000000..827dd0a --- /dev/null +++ b/build/tests/aes/_ARM7-aes-1/src/main.c @@ -0,0 +1,239 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - AES - demos - _ARM7-aes-1 + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: main.c,v $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + +#define PRIORITY 5 + +#define INPUT_DMA 4 +#define OUTPUT_DMA 5 + +#define ADATA_LENGTH 320 +#define PDATA_LENGTH (sizeof(gs_data) - ADATA_LENGTH) + +static const u128 key = { + 0x01234567, + 0x89abcdef, + 0x01234567, + 0x89abcdef +}; +static const u128 key2 = { + 0x00112233, + 0x44556677, + 0x8899aabb, + 0xccddeeff +}; +static const u96 nonce = { + 0x01234567, + 0x89abcdef, + 0x01234567 +}; +static const u32 gs_data[] ATTRIBUTE_ALIGN(32) = { + // ADATA + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + // PDATA + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567 +}; + +static u32 dataA[(sizeof(gs_data) + sizeof(u128)) / sizeof(u32)] ATTRIBUTE_ALIGN(32); +static u32 dataB[(sizeof(gs_data) + sizeof(u128)) / sizeof(u32)] ATTRIBUTE_ALIGN(32); + +//================================================================================ +static void dump(const char *str, void *ptr, u32 length) +{ + u8 *data = (u8*)ptr; + int i; + OS_TPrintf("\n[%s]:\n\t", str); + for (i = 0; i < length; i++) { + OS_TPrintf("%02X", *data++); + if ((i & 0xF) == 0xF) OS_TPrintf("\n\t"); + else OS_TPrintf(" "); + } + OS_TPrintf("\n"); +} + +#define TEST0_USE_DMA_INPUT +//#define TEST0_USE_DMA_OUTPUT +static void test0(void) +{ + OSTick begin; + + OS_TPrintf("\n%s() is starting.\n\n", __func__); + + // とりあえず、リセットする (鍵関係は何も変わらない (KEY_SELレジスタも消えるが意味は無い)) + AES_Reset(); + + // 鍵は0番目を使う + AES_SelectKey(0); + +#ifdef TEST0_USE_DMA_INPUT + // 入力DMA設定 + AES_DmaSendAsync(INPUT_DMA, gs_data, sizeof(gs_data)); // adata + pdata +#endif +#ifdef TEST0_USE_DMA_OUTPUT + // 出力DMA設定 + MI_CpuClear32(dataA, sizeof(dataA)); + AES_DmaRecvAsync(OUTPUT_DMA, dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac +#endif + + begin = OS_GetTick(); + + // AES-CCMエンコードを開始する + AES_StartCcmEnc(&nonce, ADATA_LENGTH, PDATA_LENGTH, TRUE); + +#ifdef TEST0_USE_DMA_INPUT +#ifdef TEST0_USE_DMA_OUTPUT + // DMA完了待ち (AES完了待ちでも良いでしょう) + MIi_WaitExDma(OUTPUT_DMA); +#else + // CPUで出力してみる + AES_CpuRecv(dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac +#endif +#else +#ifdef TEST0_USE_DMA_OUTPUT + // CPUで入力してみる + AES_CpuSend(gs_data, sizeof(gs_data)); // adata + pdata +#else +#error "Does not support CPU input and CPU output at same time." +#endif +#endif + + OS_TPrintf("%s: %d usec.\n", __func__, (u32)OS_TicksToMicroSeconds(OS_GetTick()-begin)); + + // 出力結果の表示 + dump(__func__, dataA, sizeof(gs_data)); +} + +static void test1(void) +{ + OSTick begin; + + OS_TPrintf("\n%s() is starting.\n\n", __func__); + + // とりあえず、リセットする (鍵関係は何も変わらない (KEY_SELレジスタも消えるが意味は無い)) + AES_Reset(); + + // 鍵を設定しない (前回の値を使いまわす) + + // 入力DMA設定 + AES_DmaSendAsync(INPUT_DMA, dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac + + // 出力バッファのクリア + MI_CpuClear32(dataB, sizeof(dataB)); + + begin = OS_GetTick(); + + // AES-CCMデコードを開始する (MACはFIFOから入力する(pdata長に含めないこと)) + AES_StartCcmDec(&nonce, NULL, ADATA_LENGTH, PDATA_LENGTH, TRUE); + + // CPUで出力してみる + AES_CpuRecv(dataB, sizeof(gs_data)); // adata + pdata + + OS_TPrintf("%s: %d usec.\n", __func__, (u32)OS_TicksToMicroSeconds(OS_GetTick()-begin)); + + // 出力結果の表示 + dump(__func__, dataB, sizeof(gs_data)); + + OS_TPrintf("Result: %s\n", AES_IsValid() ? "Success" : "Failed"); +} + +static void test2(void) +{ + OSTick begin; + + OS_TPrintf("\n%s() is starting.\n\n", __func__); + + // とりあえず、リセットする (鍵関係は何も変わらない (KEY_SELレジスタも消えるが意味は無い)) + AES_Reset(); + + // 鍵を設定する + AES_SelectKey(1); + + // 出力DMA設定 + MI_CpuClear32(dataB, sizeof(dataB)); + AES_DmaRecvAsync(OUTPUT_DMA, dataB, sizeof(gs_data)); // adata + pdata + + begin = OS_GetTick(); + + // AES-CCMデコードを開始する (MACはFIFOから入力する(pdata長に含めないこと)) + AES_StartCcmDec(&nonce, NULL, ADATA_LENGTH, PDATA_LENGTH, TRUE); + + // CPUで入力してみる + AES_CpuSend(dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac + + OS_TPrintf("%s: %d usec.\n", __func__, (u32)OS_TicksToMicroSeconds(OS_GetTick()-begin)); + + // 出力結果の表示 + dump(__func__, dataB, sizeof(gs_data)); + + OS_TPrintf("Result: %s\n", AES_IsValid() ? "Success" : "Failed"); +} + + +/*---------------------------------------------------------------------------* + Name: TwlMain + + Description: main + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void TwlMain() +{ + OS_Init(); + + OS_Printf("ARM7 starts.\n"); + + OS_InitTick(); + + OS_TPrintf("Debug Info:\n"); + OS_TPrintf("\tdataA = 0x%08X\n", dataA); + OS_TPrintf("\tdataB = 0x%08X\n", dataB); + + AES_Init(PRIORITY); // ARM9側からも利用するときのみ必要 + AES_Lock(); // ARM9側からも利用するときのみ必要 + OS_EnableIrq(); // ARM9側からも利用するときのみ必要 + + // 鍵を設定しておく + AES_SetKey(0, &key); + AES_SetKey2(1, &key, &key2); + + test0(); + test1(); + test2(); + + AES_Unlock(); // ARM9側からも利用するときのみ必要 + + // done + OS_TPrintf("\nARM7 ends.\n"); + OS_Terminate(); +} diff --git a/build/tests/aes/aes-1/Makefile b/build/tests/aes/aes-1/Makefile new file mode 100644 index 0000000..a01a83f --- /dev/null +++ b/build/tests/aes/aes-1/Makefile @@ -0,0 +1,43 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - OS - demos - _ARM7-aes-1 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +#TWL_CODEGEN = THUMB + +TARGET_BIN = main.axf + +SRCS = main.c + +#SRCDIR = # using default +#LCFILE = # using default + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tests/aes/aes-1/src/main.c b/build/tests/aes/aes-1/src/main.c new file mode 100644 index 0000000..423dd53 --- /dev/null +++ b/build/tests/aes/aes-1/src/main.c @@ -0,0 +1,340 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - AES - demos - aes-1 + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: main.c,v $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + +#define INPUT_DMA 4 +#define OUTPUT_DMA 5 + +#define ADATA_LENGTH 320 +#define PDATA_LENGTH (sizeof(gs_data) - ADATA_LENGTH) + +static const u128 key = { + 0x01234567, + 0x89abcdef, + 0x01234567, + 0x89abcdef +}; +static const u128 key2 = { + 0x00112233, + 0x44556677, + 0x8899aabb, + 0xccddeeff +}; +static const u96 nonce = { + 0x01234567, + 0x89abcdef, + 0x01234567 +}; +static const u32 gs_data[] ATTRIBUTE_ALIGN(32) = { + // ADATA + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, + // PDATA + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, + 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef, 0x01234567 +}; + +static u32 dataA[(sizeof(gs_data) + sizeof(u128)) / sizeof(u32)] ATTRIBUTE_ALIGN(32); +static u32 dataB[(sizeof(gs_data) + sizeof(u128)) / sizeof(u32)] ATTRIBUTE_ALIGN(32); + +//================================================================================ +static void dump(const char *str, void *ptr, u32 length) +{ + u8 *data = (u8*)ptr; + int i; + OS_TPrintf("\n[%s]:\n\t", str); + for (i = 0; i < length; i++) { + OS_TPrintf("%02X", *data++); + if ((i & 0xF) == 0xF) OS_TPrintf("\n\t"); + else OS_TPrintf(" "); + } + OS_TPrintf("\n"); +} + +#define TEST0_USE_DMA_INPUT +//#define TEST0_USE_DMA_OUTPUT +static void test0(void) +{ + OSTick begin; + AESResult result; + + OS_TPrintf("\n%s() is starting.\n\n", __func__); + + // とりあえず、リセットする (鍵関係は何も変わらない (KEY_SELレジスタも消えるが意味は無い)) + result = AES_Reset(); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_Reset (%d).\n", __func__, result); + } + + // 鍵は0番目を使う + result = AES_SelectKey(0); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_SelectKey (%d).\n", __func__, result); + } + +#ifdef TEST0_USE_DMA_INPUT + // 入力DMA設定 + result = AES_StartDmaSend(INPUT_DMA, gs_data, sizeof(gs_data)); // adata + pdata + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_StartDmaSend (%d).\n", __func__, result); + } +#endif + +#ifdef TEST0_USE_DMA_OUTPUT + // 出力DMA設定 + MI_CpuClear32(dataA, sizeof(dataA)); + DC_InvalidateRange(dataA, sizeof(dataA)); + result = AES_StartDmaRecv(OUTPUT_DMA, dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_StartDmaSend (%d).\n", __func__, result); + } +#endif + + begin = OS_GetTick(); + + // AES-CCMエンコードを開始する + result = AES_StartCcmEnc(&nonce, ADATA_LENGTH, PDATA_LENGTH, TRUE); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_StartCcmEnc (%d).\n", __func__, result); + } + +#ifdef TEST0_USE_DMA_INPUT +#ifdef TEST0_USE_DMA_OUTPUT + // AES完了待ち + result = AES_Wait(); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_Wait (%d).\n", __func__, result); + } +#else + // CPUで出力してみる + result = AES_CpuRecv(dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_CpuRecv (%d).\n", __func__, result); + } +#endif +#else +#ifdef TEST0_USE_DMA_OUTPUT + // CPUで入力してみる + result = AES_CpuSend(gs_data, sizeof(gs_data)); // adata + pdata + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_CpuSend (%d).\n", __func__, result); + } +#else +#error "Does not support CPU input and CPU output at same time." +#endif +#endif + + OS_TPrintf("%s: %d usec.\n", __func__, (u32)OS_TicksToMicroSeconds(OS_GetTick()-begin)); + + // 出力結果の表示 + dump(__func__, dataA, sizeof(gs_data) + sizeof(u128)); +} + +static void test1(void) +{ + OSTick begin; + AESResult result; + + OS_TPrintf("\n%s() is starting.\n\n", __func__); + + // とりあえず、リセットする (鍵関係は何も変わらない (KEY_SELレジスタも消えるが意味は無い)) + result = AES_Reset(); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_Reset (%d).\n", __func__, result); + } + + // 鍵を設定しない (前回の値を使いまわす) + + // 入力DMA設定 + DC_FlushRange(dataA, sizeof(dataA)); + result = AES_StartDmaSend(INPUT_DMA, dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_StartDmaSend (%d).\n", __func__, result); + } + + // 出力バッファのクリア + MI_CpuClear32(dataB, sizeof(dataB)); + DC_InvalidateRange(dataB, sizeof(dataB)); + + begin = OS_GetTick(); + + // AES-CCMデコードを開始する (MACはFIFOから入力する(pdata長に含めないこと)) + result = AES_StartCcmDec(&nonce, NULL, ADATA_LENGTH, PDATA_LENGTH, TRUE); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_StartCcmDec (%d).\n", __func__, result); + } + + // CPUで出力してみる + result = AES_CpuRecv(dataB, sizeof(gs_data)); // adata + pdata + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_CpuRecv (%d).\n", __func__, result); + } + + OS_TPrintf("%s: %d usec.\n", __func__, (u32)OS_TicksToMicroSeconds(OS_GetTick()-begin)); + + // 出力結果の表示 + dump("[test1]", dataA, sizeof(gs_data)); + + OS_TPrintf("Result: %s\n", AES_IsValid() ? "Success" : "Failed"); +} + +static void test2(void) +{ + OSTick begin; + AESResult result; + + OS_TPrintf("\n%s() is starting.\n\n", __func__); + + // とりあえず、リセットする (鍵関係は何も変わらない (KEY_SELレジスタも消えるが意味は無い)) + result = AES_Reset(); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_Reset (%d).\n", __func__, result); + } + + // 鍵を設定する + result = AES_SelectKey(1); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_SelectKey (%d).\n", __func__, result); + } + + // 出力DMA設定 + MI_CpuClear32(dataB, sizeof(dataB)); + DC_InvalidateRange(dataB, sizeof(dataB)); + result = AES_StartDmaRecv(OUTPUT_DMA, dataB, sizeof(gs_data)); // adata + pdata + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_StartDmaSend (%d).\n", __func__, result); + } + + begin = OS_GetTick(); + + // AES-CCMデコードを開始する (MACはFIFOから入力する(pdata長に含めないこと)) + result = AES_StartCcmDec(&nonce, NULL, ADATA_LENGTH, PDATA_LENGTH, TRUE); + { + OS_TPrintf("%s: Failed to call AES_StartCcmDec (%d).\n", __func__, result); + } + + // CPUで入力してみる + AES_CpuSend(dataA, sizeof(gs_data) + sizeof(u128)); // adata + pdata + mac + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_CpuSend (%d).\n", __func__, result); + } + + OS_TPrintf("%s: %d usec.\n", __func__, (u32)OS_TicksToMicroSeconds(OS_GetTick()-begin)); + + // 出力結果の表示 + dump(__func__, dataB, sizeof(gs_data)); + + OS_TPrintf("Result: %s\n", AES_IsValid() ? "Success" : "Failed"); +} + + +/*---------------------------------------------------------------------------* + Name: TwlMain + + Description: main + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void TwlMain() +{ + AESResult result; + + OS_Init(); + + OS_Printf("ARM9 starts.\n"); + + OS_InitTick(); + + OS_TPrintf("Debug Info:\n"); + OS_TPrintf("\tdataA = 0x%08X\n", dataA); + OS_TPrintf("\tdataB = 0x%08X\n", dataB); + + AES_Init(); + OS_TPrintf("AES_Init wad done.\n"); + + OS_EnableIrq(); + + do + { + result = AES_TryLock(); +#if 0 + if (AES_RESULT_SUCCESS_TRUE != result) + { + OS_TPrintf("%s: Failed to call AES_TryLock (%d).\n", __func__, result); + } +#endif + } + while (AES_RESULT_SUCCESS_TRUE != result); + OS_TPrintf("AES_TryLock wad done.\n"); + + // 鍵を設定しておく + result = AES_SetKey(0, &key); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_SetKey (%d).\n", __func__, result); + } + result = AES_SetKey2(1, &key, &key2); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_SetKey2 (%d).\n", __func__, result); + } + + test0(); + test1(); + test2(); + + result = AES_Unlock(); + if (AES_RESULT_SUCCESS != result) + { + OS_TPrintf("%s: Failed to call AES_Unlock (%d).\n", __func__, result); + } + + // done + OS_TPrintf("\nARM9 ends.\n"); + OS_Terminate(); +} diff --git a/include/nitro/pxi/common/fifo.h b/include/nitro/pxi/common/fifo.h new file mode 100644 index 0000000..20c1697 --- /dev/null +++ b/include/nitro/pxi/common/fifo.h @@ -0,0 +1,265 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - -include - PXI + File: pxi_fifo.c + + Copyright 2003-2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: fifo.h,v $ + Revision 1.21 2007/02/20 00:28:11 kitase_hirotake + indent source + + Revision 1.20 2006/05/22 07:01:44 okubata_ryoma + 割り込み禁止中でもPMの同期関数が動作するように修正 + + Revision 1.19 2006/05/01 01:14:54 yada + add NITRO_FIFO_TAG_CTRDG_PHI + + Revision 1.18 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.17 2005/11/01 01:17:36 okubata_ryoma + PXI_FIFO_TAG_CTRDG_Exの追加 + + Revision 1.16 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.15 2004/12/20 00:42:41 terui + WVRライブラリ用のTAGを追加。 + + Revision 1.14 2004/09/27 13:39:56 yada + add PXI_FIFO_TAG_CARD + + Revision 1.13 2004/09/13 10:50:15 yada + add PXI tag for CTRDG + + Revision 1.12 2004/09/01 04:24:35 yada + add PXI_FIFO_TAG_OS tag + + Revision 1.11 2004/07/13 08:29:12 yada + move PXI_IsArm7CallbackReady() and PXI_IsArm9CallbackReady() + from pxi_fifo.c to this header as inline. + + Revision 1.10 2004/05/14 09:34:00 yasu + add ARM9/ARM7 sync in PXI_Init + + Revision 1.9 2004/04/21 12:04:06 yasu + change pxi tag id for FS + + Revision 1.8 2004/04/15 03:01:45 yasu + add PXI_FIFO_TAG_FS + + Revision 1.7 2004/03/30 12:18:48 yasu + change parameter of PXI_SetSendCallback + + Revision 1.6 2004/03/30 10:47:05 miya + add send FIFO callback functions + + Revision 1.5 2004/03/17 02:51:35 yasu + add some tags + + Revision 1.4 2004/03/05 06:43:36 ida + add PXI_FIFO_TAG_SOUND + + Revision 1.3 2004/03/05 04:18:33 yasu + PXI_MAX_FIFO_TAG=32 fixed + + Revision 1.2 2004/03/04 12:38:50 yasu + change prefix, function name and macro + + Revision 1.1 2004/03/04 08:44:26 yasu + add defines for fifo access + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef NITRO_PXI_COMMON_FIFO_H_ +#define NITRO_PXI_COMMON_FIFO_H_ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* TAG ID definition */ +typedef enum +{ + PXI_FIFO_TAG_EX = 0, // Extension format + PXI_FIFO_TAG_USER_0, // for application programmer, use it in free + PXI_FIFO_TAG_USER_1, // for application programmer, use it in free + PXI_FIFO_TAG_SYSTEM, // SDK inner usage + PXI_FIFO_TAG_NVRAM, // NVRAM + PXI_FIFO_TAG_RTC, // RTC + PXI_FIFO_TAG_TOUCHPANEL, // Touch Panel + PXI_FIFO_TAG_SOUND, // Sound + PXI_FIFO_TAG_PM, // Power Management + PXI_FIFO_TAG_MIC, // Microphone + PXI_FIFO_TAG_WM, // Wireless Manager + PXI_FIFO_TAG_FS, // File System + PXI_FIFO_TAG_OS, // OS + PXI_FIFO_TAG_CTRDG, // Cartridge + PXI_FIFO_TAG_CARD, // Card + PXI_FIFO_TAG_WVR, // Control driving wireless library + PXI_FIFO_TAG_CTRDG_Ex, // Cartridge Ex + PXI_FIFO_TAG_CTRDG_PHI, // Cartridge PHI + PXI_FIFO_TAG_AES, // AES + + PXI_MAX_FIFO_TAG = 32 // MAX FIFO TAG +} +PXIFifoTag; + + +/* for Compatibility */ +#define PXI_FIFO_DEVICE_TEST PXI_FIFO_TAG_USR_0 +#define PXI_FIFO_DEVICE_FLASH PXI_FIFO_TAG_NVRAM +#define PXI_FIFO_DEVICE_RTC PXI_FIFO_TAG_RTC +#define PXI_FIFO_DEVICE_TOUCHPANEL PXI_FIFO_TAG_TOUCHPANEL +#define PXI_MAX_DEVICES PXI_MAX_FIFO_TAG + + +/* PXI_FIFO return code */ +typedef enum +{ + PXI_FIFO_SUCCESS = 0, + PXI_FIFO_FAIL_SEND_ERR = -1, + PXI_FIFO_FAIL_SEND_FULL = -2, + PXI_FIFO_FAIL_RECV_ERR = -3, + PXI_FIFO_FAIL_RECV_EMPTY = -4, + PXI_FIFO_NO_CALLBACK_ENTRY = -5 +} +PXIFifoStatus; + + +/* type definition */ +#define PXI_FIFOMESSAGE_BITSZ_TAG 5 +#define PXI_FIFOMESSAGE_BITSZ_ERR 1 +#define PXI_FIFOMESSAGE_BITSZ_DATA 26 +typedef union +{ + struct + { + u32 tag:PXI_FIFOMESSAGE_BITSZ_TAG; + u32 err:PXI_FIFOMESSAGE_BITSZ_ERR; + u32 data:PXI_FIFOMESSAGE_BITSZ_DATA; + } + e; + u32 raw; + +} +PXIFifoMessage; + + +// type definition +typedef void (*PXIFifoCallback) (PXIFifoTag tag, u32 data, BOOL err); +typedef void (*PXIFifoEmtpyCallback) (void); + + +/*---------------------------------------------------------------------------* + Name: PXI_IsFifoError + + Description: Check if error on fifo? + + Arguments: status Status + + Returns: None. + *---------------------------------------------------------------------------*/ +static inline BOOL PXI_IsFifoError(PXIFifoStatus status) +{ + return PXI_FIFO_SUCCESS == status; +} + + +/*---------------------------------------------------------------------------* + Name: PXI_InitFifo + + Description: initialize FIFO system + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void PXI_InitFifo(void); + + +/*---------------------------------------------------------------------------* + Name: PXI_SetFifoRecvCallback + + Description: set callback function when data arrive via FIFO + + Arguments: device_no DEVICE NO. + callback callback function to be called + + Returns: None. + *---------------------------------------------------------------------------*/ +void PXI_SetFifoRecvCallback(int fifotag, PXIFifoCallback callback); + + +/*---------------------------------------------------------------------------* + Name: PXI_IsCallbackReady + PXI_IsArm7CallbackReady + PXI_IsArm9CallbackReady + + Description: check if callback is ready + + Arguments: fifotag fifo tag NO (0-31) + proc processor name PXI_PROC_ARM9 or PXI_PROC_ARM7 + + Returns: TRUE if callback is ready + *---------------------------------------------------------------------------*/ +BOOL PXI_IsCallbackReady(int fifotag, PXIProc proc); + +static inline BOOL PXI_IsArm7CallbackReady(int fifotag) +{ + return PXI_IsCallbackReady(fifotag, PXI_PROC_ARM7); +} + +static inline BOOL PXI_IsArm9CallbackReady(int fifotag) +{ + return PXI_IsCallbackReady(fifotag, PXI_PROC_ARM9); +} + + +/*---------------------------------------------------------------------------* + Name: PXI_SetFifoSendCallback + + Description: set callback function when data is sent via FIFO + + Arguments: callback callback function to be called + + Returns: None. + *---------------------------------------------------------------------------*/ +void PXI_SetFifoSendCallback(PXIFifoEmtpyCallback callback); + + +/*---------------------------------------------------------------------------* + Name: PXI_SendWordByFifo + + Description: Send 32bit-word to anothre CPU via FIFO + + Arguments: device_no DEVICE NO. + data data(26-bit) whichi is sent + + Returns: if error occured, returns minus value + *---------------------------------------------------------------------------*/ +int PXI_SendWordByFifo(int fifotag, u32 data, BOOL err); + + +//====================================================================== +// Interrupt handler called when RECV FIFO not empty +//====================================================================== +void PXIi_HandlerRecvFifoNotEmpty(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* NITRO_PXI_COMMON_FIFO_H_ */ diff --git a/include/twl.h b/include/twl.h index c6f28ac..97b06c6 100644 --- a/include/twl.h +++ b/include/twl.h @@ -20,7 +20,7 @@ #include #include - +#include #ifdef SDK_DEBUGGER_KMC #include #endif // SDK_DEBUGGER_KMC diff --git a/include/twl/aes.h b/include/twl/aes.h new file mode 100644 index 0000000..35b08a8 --- /dev/null +++ b/include/twl/aes.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - aes - include + File: aes.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef TWL_AES_H_ +#define TWL_AES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +#include +#include +#include + +#ifdef SDK_ARM7 + +#include +#include +#include + +#else // SDK_ARM9 + +#include + +#endif + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_H_ */ + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/include/twl/aes/ARM7/control.h b/include/twl/aes/ARM7/control.h new file mode 100644 index 0000000..691522a --- /dev/null +++ b/include/twl/aes/ARM7/control.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes_sp.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_SP_H_ +#define TWL_AES_SP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +#define AES_MESSAGE_ARRAY_MAX 4 // スレッド同期用メッセージキューのサイズ +#define AES_THREAD_STACK_SIZE 256 // スレッドのスタックサイズ + +typedef enum AESLock +{ + AES_UNLOCKED = 0, + AES_LOCKED_BY_ARM7, + AES_LOCKED_BY_ARM9 +} AESLock; + +/*---------------------------------------------------------------------------* + 構造体定義 + *---------------------------------------------------------------------------*/ +// AESライブラリ用ワーク構造体 + +typedef struct AESWork +{ + OSMessageQueue msgQ; // スレッド同期用メッセージキュー + OSMessage msgArray[AES_MESSAGE_ARRAY_MAX]; + // メッセージを格納するバッファ + OSThread thread; // AES用スレッド + u64 stack[AES_THREAD_STACK_SIZE / sizeof(u64)]; + // AES用スレッドのスタック + + AESLock locked; // ロック + + u8 command; // コマンド種別 + u8 current; // 受信済みデータ個数 (バイト単位) + u8 total; // 最終データ個数 (1 + 後続コマンド*3) + u8 data[AES_PXI_DATA_SIZE_MAX]; + // ARM9からのデータ保存用 +} +AESWork; + +/*---------------------------------------------------------------------------* + 関数定義 + *---------------------------------------------------------------------------*/ +void AES_Init(u32 priority); // 初期化、及びスレッドを開始 +void AES_Lock(void); // ARM7側で使うためにロックする +BOOL AES_TryLock(void); // ARM7側で使うためにロックを試みる +void AES_Unlock(void); // ARM7側のロックを解除する + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_SP_H_ */ diff --git a/include/twl/aes/ARM7/instruction.h b/include/twl/aes/ARM7/instruction.h new file mode 100644 index 0000000..00a8c35 --- /dev/null +++ b/include/twl/aes/ARM7/instruction.h @@ -0,0 +1,300 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes_common.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_COMMON_H_ +#define TWL_AES_COMMON_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +typedef enum +{ + AES_INPUT_TYPE_WCNT_4 = (0x3UL << REG_AES_AESCNT_IFIFO_DREQ_SHIFT), + AES_INPUT_TYPE_WCNT_8 = (0x2UL << REG_AES_AESCNT_IFIFO_DREQ_SHIFT), + AES_INPUT_TYPE_WCNT_12 = (0x1UL << REG_AES_AESCNT_IFIFO_DREQ_SHIFT), + AES_INPUT_TYPE_WCNT_16 = (0x0UL << REG_AES_AESCNT_IFIFO_DREQ_SHIFT) +} +AESInputType; + +typedef enum +{ + AES_OUTPUT_TYPE_WCNT_4 = (0x0UL << REG_AES_AESCNT_OFIFO_DREQ_SHIFT), + AES_OUTPUT_TYPE_WCNT_8 = (0x1UL << REG_AES_AESCNT_OFIFO_DREQ_SHIFT), + AES_OUTPUT_TYPE_WCNT_12 = (0x2UL << REG_AES_AESCNT_OFIFO_DREQ_SHIFT), + AES_OUTPUT_TYPE_WCNT_16 = (0x3UL << REG_AES_AESCNT_OFIFO_DREQ_SHIFT) +} +AESOutputType; + +typedef enum +{ + AES_MODE_CCM_DECRYPT = (0x0UL << REG_AES_AESCNT_MODE_SHIFT), + AES_MODE_CCM_ENCRYPT = (0x1UL << REG_AES_AESCNT_MODE_SHIFT), + AES_MODE_CTR = (0x2UL << REG_AES_AESCNT_MODE_SHIFT), + AES_MODE_CTR_DECRYPT = AES_MODE_CTR, + AES_MODE_CTR_ENCRYPT = AES_MODE_CTR +} +AESMode; + +typedef enum +{ + AES_MAC_LENGTH_4 = (1 << REG_AES_AESCNT_MAC_LEN_SHIFT), + AES_MAC_LENGTH_6 = (2 << REG_AES_AESCNT_MAC_LEN_SHIFT), + AES_MAC_LENGTH_8 = (3 << REG_AES_AESCNT_MAC_LEN_SHIFT), + AES_MAC_LENGTH_10 = (4 << REG_AES_AESCNT_MAC_LEN_SHIFT), + AES_MAC_LENGTH_12 = (5 << REG_AES_AESCNT_MAC_LEN_SHIFT), + AES_MAC_LENGTH_14 = (6 << REG_AES_AESCNT_MAC_LEN_SHIFT), + AES_MAC_LENGTH_16 = (7 << REG_AES_AESCNT_MAC_LEN_SHIFT) +} +AESMacLength; + +/*---------------------------------------------------------------------------* + 構造体定義 + *---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------* + 関数定義 + *---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------* + Name: AES_Reset + + Description: stop and reset AES block. but key resisters do not clear. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Reset(void); + +/*---------------------------------------------------------------------------* + Name: AES_IsBusy + + Description: check whether AES is busy or not + + Arguments: None. + + Returns: TRUE if AES is busy, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_IsBusy(void); + +/*---------------------------------------------------------------------------* + Name: AES_Wait + + Description: wait while AES is busy + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Wait(void); + +/*---------------------------------------------------------------------------* + Name: AES_InputFifoIsFull + + Description: check whether AES input fifo is full or not + + Arguments: None. + + Returns: TRUE if AES is busy, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_InputFifoIsFull(void); + +/*---------------------------------------------------------------------------* + Name: AES_OutputFifoIsEmpty + + Description: check whether AES output fifo is empty or not + + Arguments: None. + + Returns: TRUE if AES is busy, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_OutputFifoIsEmpty(void); + +/*---------------------------------------------------------------------------* + Name: AES_WaitInputFifoNotFull + + Description: wait while AES input fifo is full. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_WaitInputFifoNotFull(void); + +/*---------------------------------------------------------------------------* + Name: AES_WaitOutputFifoNotEmpty + + Description: wait while AES output fifo is empty. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_WaitOutputFifoNotEmpty(void); + +/*---------------------------------------------------------------------------* + Name: AES_IsValid + + Description: check whether CCM decryption is valid or not. + it may return TRUE just after CCM decryption has been completed. + + Arguments: None. + + Returns: TRUE if CCM decryption was valid, FALSE otherwise + *---------------------------------------------------------------------------*/ +BOOL AES_IsValid(void); + +/*---------------------------------------------------------------------------* + Name: AES_SelectKey + + Description: select key from one of four key registers + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + + Arguments: keyNo - key group number. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SelectKey(u32 keyNo); + +/*---------------------------------------------------------------------------* + Name: AES_SetKey + + Description: set key data into key register + + Arguments: keyNo - key group number. + pKey - pointer to key data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetKey(u32 keyNo, const u128 *pKey); + +/*---------------------------------------------------------------------------* + Name: AES_SetId + + Description: set id data into id register + Note: never set key register with id and seed + + Arguments: keyNo - key group number. + pId - pointer to id data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetId(u32 keyNo, const u128 *pId); + +/*---------------------------------------------------------------------------* + Name: AES_SetSeed + + Description: set seed data into seed register + Note: automatically set associated key register with id and seed + + Arguments: keyNo - key group number. + pSeed - pointer to seed data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetSeed(u32 keyNo, const u128 *pSeed); + +/*---------------------------------------------------------------------------* + Name: AES_SetKey2 + + Description: set seed/id data into seed/id register + Note: automatically set associated key register with id and seed + + Arguments: keyNo - key group number. + pId - pointer to id data + pSeed - pointer to seed data + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SetKey2(u32 keyNo, const u128 *pId, const u128 *pSeed); + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmDec + + Description: start AES engine for AES-CCM decryption. + + Arguments: nonce - pointer to 128-bit nonce data. + mac - pointer to 128-bit mac data. + if NULL, it assumes the mac will be sent from + the input FIFO. + adataLength - length of the associated data. + pdataLength - length of the payload (encrypted) data. + it excludes mac length even if the mac will be + sent from the input FIFO. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_StartCcmDec(const u96 *nonce, const u128 *mac, u32 adataLength, u32 pdataLength, BOOL isDistA); + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmEnc + + Description: start AES engine for AES-CCM encryption. + + Arguments: nonce - pointer to 128-bit nonce data. + adataLength - length of the associated data. + pdataLength - length of the payload data. + note that output length will be extended for + the mac data. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_StartCcmEnc(const u96 *nonce, u32 adataLength, u32 pdataLength, BOOL isDistA); + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrDec + + Description: start AES engine for AES-CTR encryption/decryption. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_StartCtrDec(const u128 *iv, u32 length); +/*---------------------------------------------------------------------------* + Name: AES_StartCtrEnc + + Description: start AES engine for AES-CTR encryption/decryption. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + + Returns: None. + *---------------------------------------------------------------------------*/ +static inline void AES_StartCtrEnc(const u128 *iv, u32 length) +{ + AES_StartCtrDec(iv, length); +} + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_COMMON_H_ */ diff --git a/include/twl/aes/ARM7/transfer.h b/include/twl/aes/ARM7/transfer.h new file mode 100644 index 0000000..8180ad0 --- /dev/null +++ b/include/twl/aes/ARM7/transfer.h @@ -0,0 +1,176 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes_transfer.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_TRANSFER_H_ +#define TWL_AES_TRANSFER_H_ + +#include +#include + +#define AES_DMA_ONESHOT_SIZE 16 +#define AES_DMA_BLOCK_SIZE MI_EXDMA_BLOCK_16B +#define AES_DMA_INTERVAL 8 +#define AES_DMA_PRESCALER MI_EXDMA_PRESCALER_1 + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +/*---------------------------------------------------------------------------* + Name: AES_DmaSend + + Description: AES DMA send by AES input FIFO timing. + Should call prior to the AES_Start*(). + Sync version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + src : source address + length : transfer length (byte) (multiple of 16 bytes) + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void AES_DmaSend(u32 dmaNo, const void *src, u32 length) +{ + AES_ASSERT_DATA_LENGTH(length); + MIi_ExDmaSendCore( dmaNo, src, (void*)REG_AES_IFIFO_ADDR, length, AES_DMA_ONESHOT_SIZE, + AES_DMA_BLOCK_SIZE, AES_DMA_INTERVAL, AES_DMA_PRESCALER, + MI_EXDMA_CONTINUOUS_OFF, MI_EXDMA_SRC_RLD_OFF, MI_EXDMA_DEST_RLD_OFF, + MI_EXDMA_TIMING_AES_IN ); +} + +/*---------------------------------------------------------------------------* + Name: MIi_AesExDmaSendAsync + + Description: AES DMA send by AES input FIFO timing. + Should call prior to the AES_Start*(). + Async version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + src : source address + length : transfer length (byte) (multiple of 16 bytes) + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void AES_DmaSendAsync(u32 dmaNo, const void *src, u32 length) +{ + AES_ASSERT_DATA_LENGTH(length); + MIi_ExDmaSendAsyncCore( dmaNo, src, (void*)REG_AES_IFIFO_ADDR, length, AES_DMA_ONESHOT_SIZE, + AES_DMA_BLOCK_SIZE, AES_DMA_INTERVAL, AES_DMA_PRESCALER, + MI_EXDMA_CONTINUOUS_OFF, MI_EXDMA_SRC_RLD_OFF, MI_EXDMA_DEST_RLD_OFF, + MI_EXDMA_TIMING_AES_IN ); +} + +/*---------------------------------------------------------------------------* + Name: AES_DmaRecv + + Description: AES DMA receive by AES output FIFO timing. + Should call prior to the AES_Start*(). + Sync version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + dest : destination address + length : transfer length (byte) (multiple of 16 bytes) + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void AES_DmaRecv(u32 dmaNo, void *dest, u32 length) +{ + AES_ASSERT_DATA_LENGTH(length); + MIi_ExDmaRecvCore( dmaNo, (void*)REG_AES_OFIFO_ADDR, dest, length, AES_DMA_ONESHOT_SIZE, + AES_DMA_BLOCK_SIZE, AES_DMA_INTERVAL, AES_DMA_PRESCALER, + MI_EXDMA_CONTINUOUS_OFF, MI_EXDMA_SRC_RLD_OFF, MI_EXDMA_DEST_RLD_OFF, + MI_EXDMA_TIMING_AES_OUT ); +} + +/*---------------------------------------------------------------------------* + Name: AES_DmaRecvAsync + + Description: AES DMA receive by AES output FIFO timing. + Should call prior to the AES_Start*(). + Async version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + dest : destination address + length : transfer length (byte) (multiple of 16 bytes) + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void AES_DmaRecvAsync(u32 dmaNo, void *dest, u32 length) +{ + AES_ASSERT_DATA_LENGTH(length); + MIi_ExDmaRecvAsyncCore( dmaNo, (void*)REG_AES_OFIFO_ADDR, dest, length, AES_DMA_ONESHOT_SIZE, + AES_DMA_BLOCK_SIZE, AES_DMA_INTERVAL, AES_DMA_PRESCALER, + MI_EXDMA_CONTINUOUS_OFF, MI_EXDMA_SRC_RLD_OFF, MI_EXDMA_DEST_RLD_OFF, + MI_EXDMA_TIMING_AES_OUT ); +} + +/*---------------------------------------------------------------------------* + Name: AES_CpuSend + + Description: send data to AES input fifo by CPU. + Should call prior to the AES_Start*(). + Sync version. + + Arguments: src : source address + length : transfer length (byte) (multiple of 16 bytes) + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void AES_CpuSend(const void *src, u32 length) +{ + const u32 *ptr = src; + SDK_ASSERT(src && (src & 0x3) == 0); + AES_ASSERT_DATA_LENGTH(length); + while (length > 0) { + AES_WaitInputFifoNotFull(); + reg_AES_AES_IFIFO = *ptr++; + length -= sizeof(u32); + } +} + +/*---------------------------------------------------------------------------* + Name: AES_CpuRecv + + Description: receive data from AES input fifo by CPU. + Should call prior to the AES_Start*(). + Sync version. + + Arguments: dest : destination address + length : transfer length (byte) (multiple of 16 bytes) + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void AES_CpuRecv(void *dest, u32 length) +{ + u32 *ptr = dest; + SDK_ASSERT(dest && (dest & 0x3) == 0); + AES_ASSERT_DATA_LENGTH(length); + while (length > 0) { + AES_WaitOutputFifoNotEmpty(); + *ptr++ = reg_AES_AES_OFIFO; + length -= sizeof(u32); + } +} + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_TRANSFER_H_ */ diff --git a/include/twl/aes/ARM9/aes.h b/include/twl/aes/ARM9/aes.h new file mode 100644 index 0000000..030abb7 --- /dev/null +++ b/include/twl/aes/ARM9/aes.h @@ -0,0 +1,747 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - library - aes + File: aes.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_AES_H_ +#define TWL_AES_AES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +// 処理結果定義 +typedef enum AESResult +{ + AES_RESULT_SUCCESS = 0, + AES_RESULT_SUCCESS_TRUE, + AES_RESULT_SUCCESS_FALSE, + AES_RESULT_BUSY, + AES_RESULT_ILLEGAL_PARAMETER, + AES_RESULT_SEND_ERROR, + AES_RESULT_INVALID_COMMAND, + AES_RESULT_ILLEGAL_STATUS, + AES_RESULT_FATAL_ERROR, + AES_RESULT_MAX +} +AESResult; + +// コールバック +typedef void (*AESCallback)(AESResult result, void *arg); + + +/*---------------------------------------------------------------------------* + Name: AES_Init + + Description: AESライブラリを初期化する。 + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_Init(void); + +/*---------------------------------------------------------------------------* + Name: AES_ResetAsync + + Description: stop and reset AES block. but key resisters do not clear. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_ResetAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_Reset + + Description: stop and reset AES block. but key resisters do not clear. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_Reset(void); + +/*---------------------------------------------------------------------------* + Name: AES_IsBusyAsync + + Description: check whether AES is busy or not + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsBusyAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_IsBusy + + Description: check whether AES is busy or not + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsBusy(void); + +/*---------------------------------------------------------------------------* + Name: AES_WaitAsync + + Description: wait while AES is busy + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_Wait + + Description: wait while AES is busy + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_Wait(void); + +/*---------------------------------------------------------------------------* + Name: AES_InputFifoIsFullAsync + + Description: check whether AES input fifo is full or not + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_InputFifoIsFullAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_InputFifoIsFull + + Description: check whether AES input fifo is full or not + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_InputFifoIsFull(void); + +/*---------------------------------------------------------------------------* + Name: AES_OutputFifoIsEmptyAsync + + Description: check whether AES output fifo is empty or not + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_OutputFifoIsEmptyAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_OutputFifoIsEmpty + + Description: check whether AES output fifo is empty or not + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_OutputFifoIsEmpty(void); + +/*---------------------------------------------------------------------------* + Name: AES_WaitInputFifoNotFullAsync + + Description: wait while AES input fifo is full. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitInputFifoNotFullAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_WaitInputFifoNotFull + + Description: wait while AES input fifo is full. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitInputFifoNotFull(void); + +/*---------------------------------------------------------------------------* + Name: AES_WaitOutputFifoNotEmptyAsync + + Description: wait while AES output fifo is empty. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitOutputFifoNotEmptyAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_WaitOutputFifoNotEmpty + + Description: wait while AES output fifo is empty. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_WaitOutputFifoNotEmpty(void); + +/*---------------------------------------------------------------------------* + Name: AES_IsValidAsync + + Description: check whether CCM decryption is valid or not. + it may return TRUE just after CCM decryption has been completed. + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsValidAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_IsValid + + Description: check whether CCM decryption is valid or not. + it may return TRUE just after CCM decryption has been completed. + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_IsValid(void); + +/*---------------------------------------------------------------------------* + Name: AES_SelectKeyAsync + + Description: select key from one of four key registers + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + async version + + Arguments: keyNo - key group number. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SelectKeyAsync(u32 keyNo, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_SelectKey + + Description: select key from one of four key registers + Note: SHOULD be called after AES_Set*() prior to AES_Start*(). + sync version. + + Arguments: keyNo - key group number. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SelectKey(u32 keyNo); + +/*---------------------------------------------------------------------------* + Name: AES_SetKeyAsync + + Description: set key data into key register + async version. + + Arguments: keyNo - key group number. + pKey - pointer to key data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKeyAsync(u32 keyNo, const u128 *pKey, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_SetKey + + Description: set key data into key register + sync version. + + Arguments: keyNo - key group number. + pKey - pointer to key data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKey(u32 keyNo, const u128 *pKey); + +/*---------------------------------------------------------------------------* + Name: AES_SetIdAsync + + Description: set id data into id register + Note: never set key register with id and seed + async version. + + Arguments: keyNo - key group number. + pId - pointer to id data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetIdAsync(u32 keyNo, const u128 *pId, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_SetId + + Description: set id data into id register + Note: never set key register with id and seed + sync version. + + Arguments: keyNo - key group number. + pId - pointer to id data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetId(u32 keyNo, const u128 *pId); + +/*---------------------------------------------------------------------------* + Name: AES_SetSeedAsync + + Description: set id data into id register + Note: automatically set associated key register with id and seed + async version. + + Arguments: keyNo - key group number. + pSeed - pointer to seed data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetSeedAsync(u32 keyNo, const u128 *pSeed, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_SetSeed + + Description: set id data into id register + Note: automatically set associated key register with id and seed + sync version. + + Arguments: keyNo - key group number. + pSeed - pointer to seed data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetSeed(u32 keyNo, const u128 *pSeed); + +/*---------------------------------------------------------------------------* + Name: AES_SetKey2Async + + Description: set seed/id data into seed/id register + Note: automatically set associated key register with id and seed + async version. + + Arguments: keyNo - key group number. + pId - pointer to id data + pSeed - pointer to seed data + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKey2Async(u32 keyNo, const u128 *pId, const u128 *pSeed, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_SetKey2 + + Description: set seed/id data into seed/id register + Note: automatically set associated key register with id and seed + sync version. + + Arguments: keyNo - key group number. + pId - pointer to id data + pSeed - pointer to seed data + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_SetKey2(u32 keyNo, const u128 *pId, const u128 *pSeed); + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmDecAsync + + Description: start AES engine for AES-CCM decryption. + async version. + + Arguments: nonce - pointer to 128-bit nonce data. + mac - pointer to 128-bit mac data. + if NULL, it assumes the mac will be sent from + the input FIFO. + adataLength - length of the associated data. + pdataLength - length of the payload data. + it excludes mac length even if the mac will be + sent from the input FIFO. + isDistA - whether associated data will be output from the + output FIFO or not. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmDecAsync(const u96 *nonce, const u128 *mac, u32 adataLength, u32 pdataLength, BOOL isDistA, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmDec + + Description: start AES engine for AES-CCM decryption. + sync version. + + Arguments: nonce - pointer to 128-bit nonce data. + mac - pointer to 128-bit mac data. + if NULL, it assumes the mac will be sent from + the input FIFO. + adataLength - length of the associated data. + pdataLength - length of the payload data. + it excludes mac length even if the mac will be + sent from the input FIFO. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmDec(const u96 *nonce, const u128 *mac, u32 adataLength, u32 pdataLength, BOOL isDistA); + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmEncAsync + + Description: start AES engine for AES-CCM encryption. + async version. + + Arguments: nonce - pointer to 128-bit nonce data. + adataLength - length of the associated data. + pdataLength - length of the payload data. + note that output length will be extended for + the mac data. + isDistA - whether associated data will be output from the + output FIFO or not. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmEncAsync(const u96 *nonce, u32 adataLength, u32 pdataLength, BOOL isDistA, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_StartCcmEnc + + Description: start AES engine for AES-CCM encryption. + sync version. + + Arguments: nonce - pointer to 128-bit nonce data. + adataLength - length of the associated data. + pdataLength - length of the payload data. + note that output length will be extended for + the mac data. + isDistA - whether associated data will be output from the + output FIFO or not. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCcmEnc(const u96 *nonce, u32 adataLength, u32 pdataLength, BOOL isDistA); + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrDecAsync + + Description: start AES engine for AES-CTR encryption/decryption. + async version. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCtrDecAsync(const u128 *iv, u32 length, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrDec + + Description: start AES engine for AES-CTR encryption/decryption. + sync version. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartCtrDec(const u128 *iv, u32 length); + +/*---------------------------------------------------------------------------* + Name: AES_StartCtrEncAsync + + Description: start AES engine for AES-CTR encryption/decryption. + async version. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +static inline AESResult AES_StartCtrEncAsync(const u128 *iv, u32 length, AESCallback callback, void *arg) +{ + return AES_StartCtrDecAsync(iv, length, callback, arg); +} + +/*---------------------------------------------------------------------------* + Name: AES_StartEncDec + + Description: start AES engine for AES-CTR encryption/decryption. + sync version. + + Arguments: iv - pointer to 128-bit iv data. + length - length of the data. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +static inline AESResult AES_StartEncDec(const u128 *iv, u32 length) +{ + return AES_StartCtrDec(iv, length); +} + +/*---------------------------------------------------------------------------* + Name: AES_TryLockAsync + + Description: AESライブラリをARM7から使われないように試みる。 + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_TryLockAsync(AESCallback callback, void *arg); + +/* + 転送コマンド +*/ +/*---------------------------------------------------------------------------* + Name: AES_StartDmaSendAsync + + Description: AES DMA send by AES input FIFO timing. + Should call prior to the AES_Start*(). + async version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + src : source address + size : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaSendAsync(u32 dmaNo, const void *src, u32 size, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaSend + + Description: AES DMA send by AES input FIFO timing. + Should call prior to the AES_Start*(). + sync version. + NOTE: never wait to done to transfer! + + Arguments: dmaNo : DMA channel No. (4 - 7) + src : source address + size : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaSend(u32 dmaNo, const void *src, u32 size); + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaRecvAsync + + Description: AES DMA receive by AES output FIFO timing. + Should call prior to the AES_Start*(). + async version. + + Arguments: dmaNo : DMA channel No. (4 - 7) + dest : destination address + size : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaRecvAsync(u32 dmaNo, const void *dest, u32 size, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_StartDmaRecv + + Description: AES DMA receive by AES output FIFO timing. + Should call prior to the AES_Start*(). + sync version. + NOTE: never wait to done to transfer! + + Arguments: dmaNo : DMA channel No. (4 - 7) + dest : destination address + size : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_StartDmaRecv(u32 dmaNo, const void *dest, u32 size); + +/*---------------------------------------------------------------------------* + Name: AES_CpuSendAsync + + Description: send data to AES input fifo by CPU. + Should call prior to the AES_Start*(). + async version. + NOTE: callback will be called after to done to transfer! + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: src : source address + length : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuSendAsync(const void *src, u32 length, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_CpuSend + + Description: send data to AES input fifo by CPU. + Should call prior to the AES_Start*(). + sync version. + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: src : source address + length : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuSend(const void *src, u32 length); + +/*---------------------------------------------------------------------------* + Name: AES_CpuRecvAsync + + Description: receive data from AES input fifo by CPU. + Should call prior to the AES_Start*(). + async version. + NOTE: callback will be called after to done to transfer! + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: dest : destination address + length : transfer size (byte) (multiple of 16 bytes) + callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuRecvAsync(const void *dest, u32 length, AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_CpuRecv + + Description: receive data from AES input fifo by CPU. + Should call prior to the AES_Start*(). + sync version. + CAUTION: Cannot use AES_CPUSend*() and AES_CPURecv*() at same time. + + Arguments: dest : destination address + length : transfer size (byte) (multiple of 16 bytes) + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_CpuRecv(const void *dest, u32 length); + +/* + 特殊コマンド +*/ +/*---------------------------------------------------------------------------* + Name: AES_TryLock + + Description: AESライブラリをARM7から使われないように試みる。 + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_TryLock(void); + +/*---------------------------------------------------------------------------* + Name: AES_UnlockAsync + + Description: AESライブラリのARM9側のロックを解除する + async version. + + Arguments: callback - 非同期処理が完了した再に呼び出す関数を指定 + arg - コールバック関数の呼び出し時の引数を指定。 + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_UnlockAsync(AESCallback callback, void *arg); + +/*---------------------------------------------------------------------------* + Name: AES_Unlock + + Description: AESライブラリをARM7から使われないように試みる。 + sync version. + + Arguments: None. + + Returns: AESResult + *---------------------------------------------------------------------------*/ +AESResult AES_Unlock(void); + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_AES_H_ */ diff --git a/include/twl/aes/common/assert.h b/include/twl/aes/common/assert.h new file mode 100644 index 0000000..c36ecd0 --- /dev/null +++ b/include/twl/aes/common/assert.h @@ -0,0 +1,29 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - aes - include + File: assert.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef TWL_AES_ASSERT_H_ +#define TWL_AES_ASSERT_H_ + +/*---------------------------------------------------------------------------* + ASSERT + *---------------------------------------------------------------------------*/ +#define AES_ASSERT_KEYNO( keyNo ) SDK_ASSERTMSG( (keyNo) <= AES_KEY_MAX_NUM, "illegal AES Key No." ) +#define AES_ASSERT_DATA_LENGTH( len ) SDK_ASSERTMSG( (len) & 0xFF0000FF, "illegal data length." ) + +#endif /* TWL_AES_ASSERT_H_ */ + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/include/twl/aes/common/fifo.h b/include/twl/aes/common/fifo.h new file mode 100644 index 0000000..362799a --- /dev/null +++ b/include/twl/aes/common/fifo.h @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - aes - include + File: fifo.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef TWL_AES_FIFO_H_ +#define TWL_AES_FIFO_H_ + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +// プロトコル関連定義 +#define AES_PXI_CONTINUOUS_PACKET_MAX 20 // 連続パケットの最大連続回数 +#define AES_PXI_DATA_SIZE_MAX ((AES_PXI_CONTINUOUS_PACKET_MAX-1)*3+1) // 最大データ数 + +#define AES_PXI_START_BIT 0x02000000 // 先頭パケットを意味する +#define AES_PXI_RESULT_BIT 0x00008000 // PXIの応答を示す + +/* 先頭パケットのみの規則 */ +#define AES_PXI_DATA_NUMS_MASK 0x00ff0000 // データ数領域 +#define AES_PXI_DATA_NUMS_SHIFT 16 // データ数位置 +#define AES_PXI_COMMAND_MASK 0x00007f00 // コマンド格納部分のマスク +#define AES_PXI_COMMAND_SHIFT 8 // コマンド格納部分の位置 +#define AES_PXI_1ST_DATA_MASK 0x000000ff // 先頭パケットのデータ領域 +#define AES_PXI_1ST_DATA_SHIFT 0 // 先頭パケットのデータ位置 + +/* 後続パケットのみの規則 */ +#define AES_PXI_DATA_MASK 0x00ffffff // データ領域 +#define AES_PXI_DATA_SHIFT 0 // データ位置 + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +// PXIコマンド定義 +typedef enum AESPxiCommand +{ + AES_PXI_COMMAND_RESET = 0x00, // リセット + AES_PXI_COMMAND_IS_BUSY = 0x01, + AES_PXI_COMMAND_WAIT = 0x02, + AES_PXI_COMMAND_INPUT_FIFO_IS_FULL = 0x03, + AES_PXI_COMMAND_OUTPUT_FIFO_IS_EMPTY = 0x04, + AES_PXI_COMMAND_WAIT_INPUT_FIFO_NOT_FULL = 0x05, + AES_PXI_COMMAND_WAIT_OUTPUT_FIFO_NOT_EMPTY = 0x06, + AES_PXI_COMMAND_IS_VALID = 0x07, + AES_PXI_COMMAND_SELECT_KEY = 0x10, + AES_PXI_COMMAND_SET_KEY = 0x11, + AES_PXI_COMMAND_SET_ID = 0x12, + AES_PXI_COMMAND_SET_SEED = 0x13, + AES_PXI_COMMAND_SET_KEY2 = 0x14, + AES_PXI_COMMAND_START_CCM_DEC = 0x20, + AES_PXI_COMMAND_START_CCM_DEC_NOMAC = 0x21, + AES_PXI_COMMAND_START_CCM_ENC = 0x22, + AES_PXI_COMMAND_START_CTR = 0x23, + AES_PXI_COMMAND_START_DMA_SEND = 0x30, + AES_PXI_COMMAND_START_DMA_RECV = 0x31, + AES_PXI_COMMAND_CPU_SEND = 0x32, + AES_PXI_COMMAND_CPU_RECV = 0x33, + + AES_PXI_COMMAND_TRY_LOCK = 0x40, + AES_PXI_COMMAND_UNLOCK = 0x41 +} +AESPxiCommand; + +// 引数のサイズ定義 +typedef enum AESPxiSize +{ + AES_PXI_SIZE_RESET = 0, + AES_PXI_SIZE_IS_BUSY = 0, + AES_PXI_SIZE_WAIT = 0, + AES_PXI_SIZE_INPUT_FIFO_IS_FULL = 0, + AES_PXI_SIZE_OUTPUT_FIFO_IS_EMPTY = 0, + AES_PXI_SIZE_WAIT_INPUT_FIFO_NOT_FULL = 0, + AES_PXI_SIZE_WAIT_OUTPUT_FIFO_NOT_EMPTY = 0, + AES_PXI_SIZE_IS_VALID = 0, + AES_PXI_SIZE_SELECT_KEY = 1, // keyNo + AES_PXI_SIZE_SET_KEY = 17, // keyNo, pKey(16) + AES_PXI_SIZE_SET_ID = 17, // keyNo, pId(16) + AES_PXI_SIZE_SET_SEED = 17, // keyNo, pSeed(16) + AES_PXI_SIZE_SET_KEY2 = 33, // keyNo, pId(16), pSeed(16) + AES_PXI_SIZE_START_CCM_DEC = 37, // nonce(12), mac(16), alen(4), plen(4), isA + AES_PXI_SIZE_START_CCM_DEC_NOMAC = 21, // nonce(12), alen(4), plen(4), isA + AES_PXI_SIZE_START_CCM_ENC = 21, // nonce(12), alen(4), plen(4), isA + AES_PXI_SIZE_START_CTR = 20, // iv(16), len(4) + AES_PXI_SIZE_START_DMA_SEND = 9, // no, src(4), size(4) + AES_PXI_SIZE_START_DMA_RECV = 9, // no, dest(4), size(4) + AES_PXI_SIZE_CPU_SEND = 8, // src(4), size(4) + AES_PXI_SIZE_CPU_RECV = 8, // dest(4), size(4) + + AES_PXI_SIZE_TRY_LOCK = 0, + AES_PXI_SIZE_UNLOCK = 0 +} +AESPxiSize; + +// 応答定義 +typedef enum AESPxiResult +{ + AES_PXI_RESULT_SUCCESS = 0, // 処理成功 (void型) + AES_PXI_RESULT_SUCCESS_TRUE, // 処理成功 (BOOL型) + AES_PXI_RESULT_SUCCESS_FALSE, // 処理成功 (BOOL型) + AES_PXI_RESULT_INVALID_COMMAND, // 不正なPXIコマンド + AES_PXI_RESULT_INVALID_PARAMETER, // 不正なパラメータ + AES_PXI_RESULT_ILLEGAL_STATUS, // RTCの状態により処理を実行不能 + AES_PXI_RESULT_BUSY, // 他のリクエストを実行中 + AES_PXI_RESULT_FATAL_ERROR, // その他何らかの原因で処理に失敗 + AES_PXI_RESULT_MAX +} +AESPxiResult; + + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_FIFO_H_ */ + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/include/twl/aes/common/swap.h b/include/twl/aes/common/swap.h new file mode 100644 index 0000000..348a94c --- /dev/null +++ b/include/twl/aes/common/swap.h @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - aes - include + File: swap.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef TWL_AES_SWAP_H_ +#define TWL_AES_SWAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ + +/*---------------------------------------------------------------------------* + Name: AES_SwapWord128 + + Description: swap 32-bit array to 128-bit little endian. + for example, 0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff + are copied to 0x00112233445566778899aabbccddeeff. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapWord128(u128 *dest, const u32 *src); + +/*---------------------------------------------------------------------------* + Name: AES_SwapWord96 + + Description: swap 96-bit array to 128-bit little endian. + for example, 0x00112233, 0x44556677, 0x8899aabb + are copied to 0x00112233445566778899aabb. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapWord96(u96 *dest, const u32 *src); + +/*---------------------------------------------------------------------------* + Name: AES_SwapByte128 + + Description: swap 8-bit array to 128-bit little endian. + for example, 0x00, 0x11..., 0xff are copied to + 0x00112233445566778899aabbccddeeff. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapByte128(u128 *dest, const u8 *src); + +/*---------------------------------------------------------------------------* + Name: AES_SwapByte96 + + Description: swap 8-bit array to 96-bit little endian. + for example, 0x00, 0x11..., 0xbb are copied to + 0x00112233445566778899aabb. + + Arguments: dest - destination address + src - source address + + Returns: None. + *---------------------------------------------------------------------------*/ +void AES_SwapByte96(u96 *dest, const u8 *src); + +/*===========================================================================*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TWL_AES_SWAP_H_ */ + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/include/twl/types.h b/include/twl/types.h index 455fecd..d3e4093 100644 --- a/include/twl/types.h +++ b/include/twl/types.h @@ -27,11 +27,18 @@ extern "C" { typedef struct { - u32 e[4]; + u32 e[4]; } u128; +typedef struct +{ + u32 e[3]; +} +u96; + typedef volatile u128 vu128; +typedef volatile u96 vu96; /* io_register_list_XX.hで使用するマクロと型 @@ -39,6 +46,8 @@ typedef volatile u128 vu128; typedef u128 REGType128; typedef vu128 REGType128v; +typedef u96 REGType96; +typedef vu96 REGType96v; #ifdef __cplusplus } /* extern "C" */ diff --git a/readme-AES.txt b/readme-AES.txt new file mode 100644 index 0000000..b8ba849 --- /dev/null +++ b/readme-AES.txt @@ -0,0 +1,69 @@ +======================= +AESに関するポリシー(仮) +======================= + +現在のライブラリ実装は自由に扱える状態だが、最終的には +以下のポリシーを反映した形に制限を加える。 + + +○(予習)鍵の種類 + +次の4組の鍵の組み合わせが存在する。 + + KEY[0] ID[0] SEED[0] + KEY[1] ID[1] SEED[1] + KEY[2] ID[2] SEED[2] + KEY[3] ID[3] SEED[3] + +○(予習)鍵の基本事項 + +それぞれが独立したレジスタであるが、SEEDを設定したときに、 +SEED + ID => KEY という計算処理がおこなれる(計算式は秘密)。 +また、任意のタイミングでKEYのひとつをAESコアに送ることができる。 +このAESコアに送る作業を行わない限りAESで使用される鍵は +変更されない。 + +○(予習)種別ごとの意味合い + +KEYは一般的なAES回路として他のシステムとやり取りするような +データを取り扱うときにのみ使用する。 + +IDとSEEDは任天堂依存のやりとりで使うことになるが、 +基本的にIDの方はシステム側であらかじめ設定しておき、 +アプリケーションには操作させない。 + + +●それぞれの鍵の意味合い + + デバイス依存 アプリケーション依存 + 0: × ○ + 1: ○ ○ + 2: × × + 3: ○ × + +ここで、デバイス依存とは、eFuseの内容を反映するということ。 +また、アプリケーション依存とは、ROMヘッダ辺りを反映するということ。 + +上記の内容を反映するように、IDを設定することになる。 +0と1はブートローダーが、2と3はIPL ROMが設定する。 +(いつでも上書きできるので、IPL ROMで0と1も設定しておく) + + +●アプリケーション解放 + +アプリケーションには、KEY[0]、SEED[0]〜SEED[3]を使えるようにする。 +場合によっては、SEED[2]とSEED[3]は解放させない(2つしかない) + + +●ARM9側API案 + +鍵の種類を、DEVICE_DEPEND、APPLICATION_DEPENDの +ビットORで設定できるようにするだけ。 + +複数レジスタがあることも見せずに、値をほおり込むと +AESコアに送るところまで処理する。 + +・AES_SetNormalKey(u128 pKey) +・AES_SetSpecialKey(u128 pKey, u32 types) + +