# M2354(Jhang) Main reference: [合集·新唐基于 Cortex-M23 MCU](https://www.bilibili.com/video/BV19D4y1D7QH/?spm_id_from=333.788) ## Envrioment - 安裝[Keil](https://developer.arm.com/documentation/kan342/latest) - 安裝 [Nuvoton Nu-Link Driver](https://www.nuvoton.com.cn/export/resource-files/Nu-Link_Keil_Driver_V3.07.7246r.zip) - 安裝BSP - Project -> Option for ... ->Utilities ->Use Debug Driver 打勾並且選NULink ![](https://hackmd.io/_uploads/S1-S1jLsn.png) - Project -> Option for ... ->Debug ->Use Debug Driver 打勾並且選NULink ![](https://hackmd.io/_uploads/SkQNkiLi2.png) ## Trust Zone - secure world and non secure world - mode-> Secure 和Non secure world 有自己的mode ![](https://hackmd.io/_uploads/By47OsUs3.png) - hardware resource(SW和NSW都有自己的) - sysTick timer - MPU configuration registers - Stack register - Interrupt Handling - 避免SW的資料可以在NSW被存取。 ![](https://hackmd.io/_uploads/rJE_toUi3.png) - Memory Partitioning ### Arm® TrustZone®技術: ![](https://hackmd.io/_uploads/HJSfnswjh.png) - 將系統分為Secure World和Non-secure World,實現安全分區。 - 可以配置微控制器資源(Flash、SRAM、外設等)的安全屬性為Secure或Non-secure。 - Secure World可以訪問所有資源,包括Secure和Non-secure,Non-secure World只能訪問Non-secure資源。 - 重要數據可以放置在Secure World中,受到保護不被未授權的人員竊取或破壞。 ### 記憶體映射安全屬性配置: ![](https://hackmd.io/_uploads/BJiSnswo3.png) - M2354系列定義了由IDAU固定的記憶體映射安全屬性。但可以通過SAU更改安全配置分區,結果為IDAU和SAU之間的更高安全設定。 ![](https://hackmd.io/_uploads/Bytunivo2.png) - IDAU定義的M2354系列記憶體映射安全屬性劃分: - 記憶體映射地址的第28位用於定義安全屬性。 - 如果記憶體映射地址的第28位為0,則該區域屬於Secure(S)。 - 在Flash和SRAM區域中,記憶體映射地址的第28位為0,即為Non-secure callable(NSC)。 - 如果記憶體映射地址的第28位為1,則該區域屬於Non-secure(NS)。 - Flash的前2KB固定為Secure(S)。 - 系統相關的寄存器不劃分為特定的安全屬性,它們由當前CPU狀態確定。 - SAU配置安全屬性 ![](https://hackmd.io/_uploads/r1VMW2Psn.png) - 設置SAU_CTRL.ALLNS=0,可將所有記憶體映射配置為Secure(S)。 - 設置SAU_CTRL.ALLNS=1,可將所有記憶體映射配置為Non-secure(NS)。 - SAU_CTL:啟用SAU的使能位,以及其他設置。 - SAU_RNR:指定要設置的區域編號。 - SAU_RBAR:指定區域的起始地址。 - SAU_RLAR:指定區域的結束地址和屬性,可設置為Non-secure callable(NSC)。 - 未由SAU指定的區域的安全屬性是Secure(S)。 - 安全屬性配置的優先級:Secure(S)> Non-secure callable(NSC)> Non-secure(NS)。 ### 安全和非安全狀態切換: ![](https://hackmd.io/_uploads/SyVwaiDsh.png) - Secure code可以調用Non-secure function,進入Non-secure狀態。 ![](https://hackmd.io/_uploads/rkrA6sDjn.png) - Non-secure code不能直接調用Secure function,必須通過Non-secure callable entry function進入Secure狀態。 ![](https://hackmd.io/_uploads/BkYi6ovi3.png) - 使用BLXNS指令切換狀態。 ### 記憶體地址安全檢查: - Secure code提供Non-secure callable function,以便Non-secure code調用Secure function。 - 使用“cmse_check_address_range”內嵌函數進行記憶體地址的安全檢查。 - 將“flags”參數設置為“CMSE_NONSECURE”,並檢查範圍從“p”到“p+size-1”。 - 如果被檢查的地址都在Secure記憶體中,返回地址p;否則,返回NULL。 - 另一個內嵌函數“cmse_check_pointed_object”也可用於檢查記憶體地址安全性,檢查大小為1。 --- ### 其他硬體安全屬性 --- #### Flash - reset 後都為secure state。 - 用FMC來設定,透過NSCBA來設定NonSecure的起始位置![](https://hackmd.io/_uploads/rJ1cP8C23.png) #### SRAM 和周邊 ![](https://hackmd.io/_uploads/S1Rd_LA2h.png) - reset 後都為secure state。 - 使用SAU來設定 - SRAM - 透過SRAMNSSET![](https://hackmd.io/_uploads/Hk6sOUCn3.png) - 周邊(除了GPIO) - 透過PNSSET0 ~ PNSSET6![](https://hackmd.io/_uploads/Sy8GYU0nh.png) - GPIO - 透過IONSSET![](https://hackmd.io/_uploads/SyTYtL023.png) --- ### other secure function --- - 加密加速器![](https://hackmd.io/_uploads/rk5rcUChn.png) - Secure bootloader![](https://hackmd.io/_uploads/Bk00cIR22.png) - 本身不可改變和讀取 - 用來檢查Flash裡面的firmware code 是否完整且未被竄改。 - KPROM![](https://hackmd.io/_uploads/rJePjLC3n.png) - 用來保護Flash的讀寫 - 在讀寫之前要要傳入key並與KPROM的key一樣才會讀寫成功 - XOM![](https://hackmd.io/_uploads/r1RhoIR22.png) - 類似黑盒的概念 - Flash lock bits![](https://hackmd.io/_uploads/HkxEnLChn.png) - 如名字所述 - secure debug![](https://hackmd.io/_uploads/ByFunLA3n.png) - 透過scrlock, arlock來設定 - 防竄改機制![](https://hackmd.io/_uploads/rJJfT8R23.png) - 有6個tamper pin 可以組成三組tamper loop 來確認有沒有被竄改 ## GPIO ### 對照表 - **source: UM p44~~** - ![](https://hackmd.io/_uploads/Bk8mmE7Tn.png) - ![](https://hackmd.io/_uploads/SyZVm4X62.png) DM(Data mask)這個pin,它在電路設計上跟data pin(DQ)是一樣的,一般是8個DQ會搭配1個DM,它是在把data寫入DRAM時,去框出data pin(DQ)裡的data是不是有效的,如果DQ是DM所框住的範圍,將會視為無效的。 ### registers - Port A-H I/O Mode Control (MODE) - 位址偏移:0x00 / 0x40 / 0x80 / 0xC0 / 0x100 / 0x140 / 0x180 / 0x1C0 - 用途:控制 Port A-H 的引腳的輸入/輸出模式。 - Port A-H Digital Input Path Disable Control (DINOFF) - 位址偏移:0x04 / 0x44 / 0x84 / 0xC4 / 0x104 / 0x144 / 0x184 / 0x1C4 - 用途:控制 Port A-H 的引腳的數位輸入路徑是否被禁用。 - Port A-H Data Output Value (DOUT) - 位址偏移:0x08 / 0x48 / 0x88 / 0xC8 / 0x108 / 0x148 / 0x188 / 0x1C8 - 用途:設定 Port A-H 的引腳的數位輸出值。 - Port A-H Data Output Write Mask (DATMSK) - 位址偏移:0x0C / 0x4C / 0x8C / 0xCC / 0x10C / 0x14C / 0x18C / 0x1CC - 用途:設定 Port A-H 的引腳的數位輸出寫入遮罩。 - Port A-H Pin Value (PIN) - 位址偏移:0x10 / 0x50 / 0x90 / 0xD0 / 0x110 / 0x150 / 0x190 / 0x1D0 - 用途:讀取 Port A-H 的引腳的數位輸入值。 - Port A-H De-Bounce Enable Control (DBEN) - 位址偏移:0x14 / 0x54 / 0x94 / 0xD4 / 0x114 / 0x154 / 0x194 / 0x1D4 - 用途:控制 Port A-H 的引腳的去彈跳功能是否啟用。 - Port A-H Interrupt Trigger Type Control (INTTYPE) - 位址偏移:0x18 / 0x58 / 0x98 / 0xD8 / 0x118 / 0x158 / 0x198 / 0x1D8 - 用途:設定 Port A-H 的引腳的中斷觸發方式。 - Port A-H Interrupt Enable Control (INTEN) - 位址偏移:0x1C / 0x5C / 0x9C / 0xDC / 0x11C / 0x15C / 0x19C / 0x1DC - 用途:控制 Port A-H 的引腳的中斷是否啟用。 - Port A-H Interrupt Source Flag (INTSRC) - 位址偏移:0x20 / 0x60 / 0xA0 / 0xE0 / 0x120 / 0x160 / 0x1A0 / 0x1E0 - 用途:顯示 Port A-H 的引腳的中斷來源標誌。 - Port A-H Input Schmitt Trigger Enable (SMTEN) - 位址偏移:0x24 / 0x64 / 0xA4 / 0xE4 / 0x124 / 0x164 / 0x1A4 / 0x1E4 - 用途:控制 Port A-H 的引腳的輸入 Schmitt 觸發功能是否啟用。 - 施密特觸發器為一正回饋的比較電路,當輸入電壓高於設定之閥值電壓時,輸出一正電壓;反之,當輸入電壓低於設定之閥值電壓時,輸出一低電壓。 - Port A-H High Slew Rate Control (SLEWCTL) - 位址偏移:0x28 / 0x68 / 0xA8 / 0xE8 / 0x128 / 0x168 / 0x1A8 / 0x1E8 - 用途:控制 Port A-H 的引腳的高攀升率功能是否啟用。 - Port A-H Pull-up and Pull-down Selection Register (PUSEL) - 位址偏移:0x30 / 0x70 / 0xB0 / 0xF0 / 0x130 / 0x170 / 0x1B0 / 0x1F0 - 用途:設定 Port A-H 的引腳的上拉和下拉電阻選擇。 - Port A-H Interrupt De-bounce Control (DBCTL) - 位址偏移:0x34 / 0x74 / 0xB4 / 0xF4 / 0x134 / 0x174 / 0x1B4 / 0x1F4 - 用途:設定 Port A-H 的引腳的中斷去彈跳控制。 ### 基本函式 - GPIO_SetMode : - 功能:設定指定 GPIO 引腳的操作模式。 - 用法:GPIO_SetMode(PB, BIT3, GPIO_MODE_INPUT); - 參數: - port: 要設定的 GPIO 端口,例如 PA, PB ...。 - u32PinMask: 欲設定的引腳遮罩,可以是位遮罩,表示要設定的引腳。 - ![](https://hackmd.io/_uploads/HyKkB4mT2.png) - u32Mode: 要設定的操作模式,可以是以下之一: - GPIO_MODE_INPUT: 設定為輸入模式。 - GPIO_MODE_OUTPUT: 設定為輸出模式。 - GPIO_MODE_OPEN_DRAIN: 設定為開漏輸出模式。 - GPIO_MODE_QUASI: 設定為準穩態輸出模式。![](https://hackmd.io/_uploads/Sk9EBEQT2.png) - GPIO_EnableInt : - 功能:啟用指定 GPIO 引腳的中斷功能。 - 用法:GPIO_EnableInt(PB, 2, GPIO_INT_RISING); - 參數: - port: 要啟用中斷的 GPIO 端口,例如 PA, PB ...。 - u32Pin: 欲啟用中斷的引腳編號。![](https://hackmd.io/_uploads/SJDQ84XT2.png) - u32IntAttribs: 中斷觸發方式,可以是以下之一: - GPIO_INT_RISING: 上升沿觸發。 - GPIO_INT_FALLING: 下降沿觸發。 - GPIO_INT_BOTH_EDGE: 雙邊緣觸發。 - GPIO_INT_HIGH: 高電平觸發。 - GPIO_INT_LOW: 低電平觸發。 - 通常會接著 NVIC_EnableIRQ(...) - GPIO_DisableInt : - 功能:停用指定 GPIO 引腳的中斷功能。 - 用法:GPIO_DisableInt(PB, 2); - 參數: - port: 要停用中斷的 GPIO 端口,例如 PA, PB ...。 - u32Pin: 欲停用中斷的引腳編號。 - GPIO_SetSlewCtl : - 功能:設定指定 GPIO 引腳的斜率控制模式,擺幅率是輸出電壓變化的速率。對於輸入引腳,此設置不產生任何影響。 - 用法:GPIO_SetSlewCtl(PB, BIT2, GPIO_SLEWCTL_HIGH); - 參數: - port: 要設定斜率控制的 GPIO 端口,例如 PA, PB ...。 - u32PinMask: 欲設定的引腳遮罩,可以是位遮罩,表示要設定的引腳。![](https://hackmd.io/_uploads/HyPXn47Th.png) - u32Mode: 要設定的斜率控制模式,可以是以下之一: - GPIO_SLEWCTL_NORMAL: 標準模式(最大 40 MHz 在 2.7V)。 - GPIO_SLEWCTL_HIGH: 高速模式(最大 80 MHz 在 2.7V)。 - GPIO_SLEWCTL_FAST: 快速模式(最大 100 MHz 在 2.7V)。 - GPIO_SetPullCtl : - 功能:設定指定 GPIO 引腳的上拉和下拉控制模式。 - 用法:GPIO_SetPullCtl(PB, BIT2, GPIO_PUSEL_PULL_UP); - 參數: - port: 要設定上拉和下拉的 GPIO 端口,例如 PA, PB ...。 - u32PinMask: 欲設定的引腳遮罩,可以是位遮罩,表示要設定的引腳。![](https://hackmd.io/_uploads/BkDF2EQ6n.png) - u32Mode: 要設定的上拉或下拉控制模式,可以是以下之一: - GPIO_PUSEL_DISABLE: 停用上拉和下拉電阻。 - GPIO_PUSEL_PULL_UP: 啟用上拉電阻。 - GPIO_PUSEL_PULL_DOWN: 啟用下拉電阻。 ### 進階函式 - GPIO_CLR_INT_FLAG : - 功能:清除指定 GPIO 引腳的中斷旗標。 - 用法:GPIO_CLR_INT_FLAG(port, u32PinMask) => ((port)->INTSRC = (u32PinMask)) - 參數: - port: 要清除中斷旗標的 GPIO 端口,例如 PA。 - u32PinMask: 欲清除中斷旗標的引腳遮罩,可以是位遮罩,表示要清除的引腳,例如 BIT3。 - GPIO_DISABLE_DEBOUNCE : - 功能:停用指定 GPIO 引腳的去彈跳功能。 - 用法:GPIO_DISABLE_DEBOUNCE(port, u32PinMask) => ((port)->DBEN &= ~(u32PinMask)) - 參數: - port: 要停用去彈跳的 GPIO 端口,例如 PA。 - u32PinMask: 欲停用去彈跳的引腳遮罩,可以是位遮罩,表示要停用去彈跳的引腳,例如 BIT3。 - GPIO_ENABLE_DEBOUNCE : - 功能:啟用指定 GPIO 引腳的去彈跳功能。 - 用法:GPIO_ENABLE_DEBOUNCE(port, u32PinMask) => ((port)->DBEN |= (u32PinMask)) - 參數: - port: 要啟用去彈跳的 GPIO 端口,例如 PA。 - u32PinMask: 欲啟用去彈跳的引腳遮罩,可以是位遮罩,表示要啟用去彈跳的引腳,例如 BIT3。 - GPIO_DISABLE_DIGITAL_PATH : - 功能:停用指定 GPIO 引腳的數位輸入路徑。 - 用法:GPIO_DISABLE_DIGITAL_PATH(port, u32PinMask) => ((port)->DINOFF |= ((u32PinMask)<<16)) - 參數: - port: 要停用數位輸入路徑的 GPIO 端口,例如 PA。 - u32PinMask: 欲停用數位輸入路徑的引腳遮罩,可以是位遮罩,表示要停用數位輸入路徑的引腳,例如 BIT3。 - GPIO_ENABLE_DIGITAL_PATH : - 功能:啟用指定 GPIO 引腳的數位輸入路徑。 - 用法:GPIO_ENABLE_DIGITAL_PATH(port, u32PinMask) => ((port)->DINOFF &= ~((u32PinMask)<<16)) - 參數: - port: 要啟用數位輸入路徑的 GPIO 端口,例如 PA。 - u32PinMask: 欲啟用數位輸入路徑的引腳遮罩,可以是位遮罩,表示要啟用數位輸入路徑的引腳,例如 BIT3。 - GPIO_DISABLE_DOUT_MASK : - 功能:停用指定 GPIO 引腳的數位輸出遮罩。 - 用法:GPIO_DISABLE_DOUT_MASK(port, u32PinMask) => ((port)->DATMSK &= ~(u32PinMask)) - 參數: - port: 要停用數位輸出遮罩的 GPIO 端口,例如 PA。 - u32PinMask: 欲停用數位輸出遮罩的引腳遮罩,可以是位遮罩,表示要停用數位輸出遮罩的引腳,例如 BIT3。 - GPIO_ENABLE_DOUT_MASK : - 功能:啟用指定 GPIO 引腳的數位輸出遮罩。 - 用法:GPIO_ENABLE_DOUT_MASK(port, u32PinMask) => ((port)->DATMSK |= (u32PinMask)) - 參數: - port: 要啟用數位輸出遮罩的 GPIO 端口,例如 PA。 - u32PinMask: 欲啟用數位輸出遮罩的引腳遮罩,可以是位遮罩,表示要啟用數位輸出遮罩的引腳,例如 BIT3。 - GPIO_GET_INT_FLAG : - 功能:獲取指定 GPIO 引腳的中斷旗標。 - 用法:GPIO_GET_INT_FLAG(port, u32PinMask) ((port)->INTSRC & (u32PinMask)) - 參數: - port: 要獲取中斷旗標的 GPIO 端口,例如 PA。 - u32PinMask: 欲獲取中斷旗標的引腳遮罩,可以是位遮罩,表示要獲取中斷旗標的引腳,例如 BIT3。 - GPIO_SET_DEBOUNCE_TIME : - - 功能:設定去彈跳採樣週期時間。 - 用法:GPIO_SET_DEBOUNCE_TIME(port, u32ClkSrc, u32ClkSel) => ((port)->DBCTL = (GPIO_DBCTL_ICLKON_Msk | (u32ClkSrc) | (u32ClkSel))) - 參數: - port: 要設定去彈跳採樣週期時間的 GPIO 端口,例如 PA。 - u32ClkSrc: 去彈跳計數器的時脈源,可以是 GPIO_DBCTL_DBCLKSRC_HCLK 或 - GPIO_DBCTL_DBCLKSRC_LIRC。 - u32ClkSel: 去彈跳採樣週期的選擇,可以是列出的各種選項之一。![](https://hackmd.io/_uploads/HyaHtHQ6n.png) - GPIO_GET_IN_DATA : - 功能:獲取指定 GPIO 端口的輸入資料。 - 用法:GPIO_GET_IN_DATA(port) => ((port)->PIN) - 參數: - port: 要獲取輸入資料的 GPIO 端口,例如 PA。 - GPIO_SET_OUT_DATA : - 功能:設定指定 GPIO 端口的輸出資料。 - 用法:GPIO_SET_OUT_DATA(port, u32Data) ((port)->DOUT = (u32Data)) - 參數: - port: 要設定輸出資料的 GPIO 端口,例如 PA。 - u32Data: 要輸出的 GPIO 資料。 - GPIO_TOGGLE: - 功能:切換指定 GPIO 引腳的狀態。 - 用法:GPIO_TOGGLE(u32Pin) => ((u32Pin) ^= 1) - 參數: - u32Pin: 欲切換狀態的引腳編號,例如 PA3。 ### Example ![](https://hackmd.io/_uploads/ByNne8mpn.png) --- ![](https://hackmd.io/_uploads/HkgJ-8X6h.png) --- ![](https://hackmd.io/_uploads/BJExbLmah.png) ## CRPT module ### Init - 在SYS_INIT要加上 ```c /* Enable CRPT module clock */ CLK_EnableModuleClock(CRPT_MODULE); ``` - 通常在算下列加解密的計算之前會開啟各自的INT ```c NVIC_EnableIRQ(CRPT_IRQn); AES_ENABLE_INT(CRPT); ``` - 計算完之後會raise interrupt就會跳到Handler ```c void CRPT_IRQHandler(void) { if (AES_GET_INT_FLAG(CRPT)) //其中要確認是不是正確的加解密算法呼叫的 { g_AES_done = 1; AES_CLR_INT_FLAG(CRPT); } } ``` ### PRNG (Pseudo-Random Number Generator,偽隨機數產生器) - **函式名稱:** PRNG_Open - **用途:** 開啟 PRNG(Pseudo-Random Number Generator,偽隨機數產生器)功能 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32KeySize`:PRNG 金鑰大小,可選取以下之一: - PRNG_KEY_SIZE_128 - PRNG_KEY_SIZE_192 - PRNG_KEY_SIZE_224 - PRNG_KEY_SIZE_255 - PRNG_KEY_SIZE_256 - PRNG_KEY_SIZE_283 - PRNG_KEY_SIZE_384 - PRNG_KEY_SIZE_409 - PRNG_KEY_SIZE_512 - PRNG_KEY_SIZE_521 - PRNG_KEY_SIZE_571 - `u32SeedReload`:PRNG 種子載入選項,可選取以下之一: - PRNG_SEED_CONT - PRNG_SEED_RELOAD - `u32Seed`:新的種子(僅在 `u32SeedReload` 為 `PRNG_SEED_RELOAD` 時有效) - **範例:** ```c PRNG_Open(CRPT_T *crpt, uint32_t u32KeySize, uint32_t u32SeedReload, uint32_t u32Seed) ``` - **函式名稱:** PRNG_Start - **用途:** 開始生成一組 PRNG 金鑰。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - **返回值:** - `0`:成功生成 PRNG 金鑰。 - `-1`:生成 PRNG 金鑰超時。 - **範例:** ```c int32_t PRNG_Start(CRPT_T *crpt) ``` - **函式名稱:** PRNG_Read - **用途:** 讀取 PRNG 金鑰。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32RandKey`:用於儲存新生成的 PRNG 金鑰的緩衝區 - **返回值:** 無 - **範例:** ```c void PRNG_Read(CRPT_T *crpt, uint32_t u32RandKey[]) ``` - sample - ```c ... PRNG_Open(CRPT, u32KeySize, 1, 0x55); for(i = 0; i < GENERATE_COUNT; i++) { g_PRNG_done = 0; /* Start random number generator */ PRNG_Start(CRPT); /* Waiting for number ready */ u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */ while(!g_PRNG_done) { if(--u32TimeOutCnt == 0) { printf("Wait for PRNG time-out!\n"); return -1; } } /* Read random number */ memset(au32PrngData, 0, sizeof(au32PrngData)); PRNG_Read(CRPT, au32PrngData); printf("PRNG DATA ==>\n"); printf(" 0x%08x 0x%08x 0x%08x 0x%08x\n", au32PrngData[0], au32PrngData[1], au32PrngData[2], au32PrngData[3]); printf(" 0x%08x 0x%08x 0x%08x 0x%08x\n", au32PrngData[4], au32PrngData[5], au32PrngData[6], au32PrngData[7]); } ... ``` ### AES - **函式名稱:** AES_Open - **用途:** 開啟 AES 加密/解密功能。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32Channel`:AES 通道,必須為 0~3 之間的數字 - `u32EncDec`:1 表示 AES 加密;0 表示 AES 解密 - `u32OpMode`:AES 操作模式,包括: - AES_MODE_ECB - AES_MODE_CBC - AES_MODE_CFB - AES_MODE_OFB - AES_MODE_CTR - AES_MODE_CBC_CS1 - AES_MODE_CBC_CS2 - AES_MODE_CBC_CS3 - AES_MODE_GCM - AES_MODE_GHASH - AES_MODE_CCM - `u32KeySize`:AES 金鑰大小,包括: - AES_KEY_SIZE_128 - AES_KEY_SIZE_192 - AES_KEY_SIZE_256 - `u32SwapType`:AES 輸入/輸出資料交換控制(資料交換控制的概念就是為了讓你能夠調整輸入和輸出資料的排列或格式),包括: - AES_NO_SWAP - AES_OUT_SWAP - AES_IN_SWAP - AES_IN_OUT_SWAP - **返回值:** 無 - **範例:** ```c void AES_Open(CRPT_T *crpt, uint32_t u32Channel, uint32_t u32EncDec, uint32_t u32OpMode, uint32_t u32KeySize, uint32_t u32SwapType) ``` - **函式名稱:** AES_Start - **用途:** 開始 AES 加密/解密。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32Channel`:AES 通道,必須為 0~3 之間的數字 - `u32DMAMode`:AES DMA 控制,包括: - CRYPTO_DMA_ONE_SHOT:一次性 AES 加密/解密 - CRYPTO_DMA_CONTINUE:連續 AES 加密/解密 - CRYPTO_DMA_LAST:一系列 AES_Start 中的最後一次加密/解密 - **返回值:** 無 - **範例:** ```c void AES_Start(CRPT_T *crpt, int32_t u32Channel, uint32_t u32DMAMode) ``` - **函式名稱:** AES_SetKey - **用途:** 設置 AES 金鑰。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32Channel`:AES 通道,必須為 0~3 之間的數字 - `au32Keys`:包含 AES 金鑰的字陣列 - `u32KeySize`:AES 金鑰大小,包括: - AES_KEY_SIZE_128 - AES_KEY_SIZE_192 - AES_KEY_SIZE_256 - **返回值:** 無 - **範例:** ```c void AES_SetKey(CRPT_T *crpt, uint32_t u32Channel, uint32_t au32Keys[], uint32_t u32KeySize) ``` - **函式名稱:** AES_SetKey_KS - **用途:** 設置 Key Store 中的 AES 金鑰索引。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `mem`:Key Store 金鑰的記憶體類型,可選擇: - KS_SRAM - KS_FLASH - KS_OTP - `i32KeyIdx`:Key Store 中金鑰的索引 - **返回值:** 無 - **範例:** ```c void AES_SetKey_KS(CRPT_T *crpt, KS_MEM_Type mem, int32_t i32KeyIdx) ``` - **函式名稱:** AES_SetInitVect - **用途:** 設置 AES 初始向量。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32Channel`:AES 通道,必須為 0~3 之間的數字 - `au32IV`:包含 AES 初始向量的四個字陣列 - **返回值:** 無 - **範例:** ```c void AES_SetInitVect(CRPT_T *crpt, uint32_t u32Channel, uint32_t au32IV[]) ``` - **函式名稱:** AES_SetDMATransfer - **用途:** 設置 AES DMA 傳輸配置。(DMA代表“直接存儲器存取”(Direct Memory Access)) - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32Channel`:AES 通道,必須為 0~3 之間的數字 - `u32SrcAddr`:AES DMA 源位址 - `u32DstAddr`:AES DMA 目標位址 - `u32TransCnt`:AES DMA 傳輸位元組數量 - **返回值:** 無 - **範例:** ```c void AES_SetDMATransfer(CRPT_T *crpt, uint32_t u32Channel, uint32_t u32SrcAddr, uint32_t u32DstAddr, uint32_t u32TransCnt) ``` - sample - ```c ... AES_Open(CRPT, 0, 1, AES_MODE_ECB, AES_KEY_SIZE_128, AES_IN_OUT_SWAP); AES_SetKey(CRPT, 0, au32MyAESKey, AES_KEY_SIZE_128); AES_SetInitVect(CRPT, 0, au32MyAESIV); AES_SetDMATransfer(CRPT, 0, (uint32_t)au8InputData, (uint32_t)au8OutputData, sizeof(au8InputData)); g_AES_done = 0; /* Start AES Encrypt */ AES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT); /* Waiting for AES calculation */ u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */ while(!g_AES_done) { if(--u32TimeOutCnt == 0) { printf("Wait for AES encrypt done time-out!\n"); return -1; } } printf("AES encrypt done.\n\n"); DumpBuffHex(au8OutputData, sizeof(au8InputData)); ... ``` ### SHA - **函式名稱:** SHA_Open - **用途:** 開啟 SHA 加密功能。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32OpMode`:SHA 操作模式,包括: - SHA_MODE_SHA1 - SHA_MODE_SHA224 - SHA_MODE_SHA256 - ... - `u32SwapType`:SHA 輸入/輸出資料交換控制,包括: - SHA_NO_SWAP - SHA_OUT_SWAP - SHA_IN_SWAP - SHA_IN_OUT_SWAP - `hmac_key_len`:HMAC 金鑰的位元組數量 - **返回值:** 無 - **範例:** ```c void SHA_Open(CRPT_T *crpt, uint32_t u32OpMode, uint32_t u32SwapType, uint32_t hmac_key_len) ``` - **函式名稱:** SHA_Start - **用途:** 開始 SHA 加密。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32DMAMode`:TDES DMA 控制,包括: - CRYPTO_DMA_ONE_SHOT:一次性 SHA 加密 - CRYPTO_DMA_CONTINUE:連續 SHA 加密 - CRYPTO_DMA_LAST:一系列 SHA_Start 中的最後一次加密 - **返回值:** 無 - **範例:** ```c void SHA_Start(CRPT_T *crpt, uint32_t u32DMAMode) ``` - **函式名稱:** SHA_SetDMATransfer - **用途:** 設置 SHA DMA 傳輸。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32SrcAddr`:SHA DMA 源位址 - `u32TransCnt`:SHA DMA 傳輸位元組數量 - **返回值:** 無 - **範例:** ```c void SHA_SetDMATransfer(CRPT_T *crpt, uint32_t u32SrcAddr, uint32_t u32TransCnt) ``` - **函式名稱:** SHA_Read - **用途:** 讀取 SHA 雜湊值。 - **參數:** - `crpt`:指向 CRYPTO 模組的指標 - `u32Digest`:SHA 加密輸出雜湊值 - **返回值:** 無 - **範例:** ```c void SHA_Read(CRPT_T *crpt, uint32_t u32Digest[]) ``` - sample - ```c ... SHA_Open(CRPT, SHA_MODE_SHA1, SHA_IN_SWAP, 0); SHA_SetDMATransfer(CRPT, (uint32_t)&g_au8ShaData[0], (uint32_t)g_i32DataLen / 8); printf("Key len= %d bits\n", g_i32DataLen); g_SHA_done = 0; /* Start SHA calculation */ SHA_Start(CRPT, CRYPTO_DMA_ONE_SHOT); /* Waiting for SHA calcuation done */ u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */ while(!g_SHA_done) { if(--u32TimeOutCnt == 0) { printf("Wait for SHA calcuation done time-out!\n"); return (-1); } } /* Read SHA calculation result */ SHA_Read(CRPT, au32OutputDigest); ... ``` - HMAC - sample - ```c ... SHA_Open(CRPT, u32OpMode, SHA_IN_OUT_SWAP, u32KeyLen); SHA_SetDMATransfer(CRPT, (uint32_t)&gau8HMACSrc[0], u32MsgLen + u32KeyLenAlign); g_HMAC_done = 0; CRPT->HMAC_CTL |= CRPT_HMAC_CTL_START_Msk | CRPT_HMAC_CTL_DMAEN_Msk | CRPT_HMAC_CTL_DMALAST_Msk; u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */ while(!g_HMAC_done) { if(--u32TimeOutCnt == 0) { printf("Wait for HMAC time-out!\n"); return -1; } } printf("\nHMAC Output:\n"); pu8 = (uint8_t *)&CRPT->HMAC_DGST[0]; for(i = 0; i < 32; i++) { printf("%02x", pu8[i]); } printf("\n"); ... ``` ### RSA - 函數名: RSA_Open - **用途**:打開 RSA 加密/解密功能。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - `u32OpMode`:RSA 操作模式,可選以下之一: - `RSA_MODE_NORMAL` - `RSA_MODE_CRT` - `RSA_MODE_CRTBYPASS` - `RSA_MODE_SCAP` - `RSA_MODE_CRT_SCAP` - `RSA_MODE_CRTBYPASS_SCAP` - `u32KeySize`:RSA 密鑰大小,任選以下之一: - `RSA_KEY_SIZE_1024` - `RSA_KEY_SIZE_2048` - `RSA_KEY_SIZE_3072` - `RSA_KEY_SIZE_4096` - `psRSA_Buf`:RSA 坐標軸結構特定體的操作指針。用戶應首先為 RSA 坐標軸模式聲明。 - `u32BufSize`:RSA 中心尺寸。 - `u32UseKS`:是否使用密鑰存儲功能,任選其一: - `0`:不使用倉儲功能 - `1`:使用密鑰存儲功能 - **返回值**: - `0`:成功。 - `-1`:RSA 坐標體的指針為空。 - 函數名: RSA_SetKey - **用途**:設置 RSA 密鑰。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - `Key`:私鑰或基線。 - **返回值**: - `0`:成功。 - `-1`:RSA 坐標體的指針為空。 - 函數名: RSA_SetDMATransfer - **用途**:設置 RSA DMA 傳輸配置。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - `Src`:RSA DMA 來源數據。 - `n`:公私簽名的模數。 - `P`:CRT/SCAP 模式下的模數操作因子 P。 - `Q`:CRT/SCAP 模式下的模組數操作因子 Q。 - **返回值**: - `0`:成功。 - `-1`:RSA 坐標體的指針為空。 - 函數名: RSA_Start - **用途**:啟動 RSA 加密/解密。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - **返回值**:無。 - 函數名: RSA_Read - **用途**:讀取 RSA 輸出數據。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - `Output`:RSA 操作的輸出數據。 - **返回值**: - `0`:成功。 - `-1`:RSA 坐標體的指針為空。 - 函數名: RSA_SetKey_KS - **用途**:設置從密鑰中存儲讀取的 RSA 密鑰。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - `u32KeyNum`:密鑰存儲中的私鑰或公鑰編號。 - `u32KSMemType`:從密鑰存儲中讀取密鑰的內存類型,可選以下之一: - `KS_SRAM` - `KS_FLASH` - `KS_OTP` - `u32BlindKeyNum`:SCAP 模式下 SRAM 按鍵存儲中的盲按鍵編號。 - **返回值**:0:成功。 - 函數名: RSA_SetDMATransfer_KS - **用途**:在使用密鑰時存儲設置 RSA DMA 傳輸配置。 - **參數**: - `crpt`:指向 CRYPTO 模組的指針。 - `u32OpMode`:RSA 操作模式,可選以下之一: - `RSA_MODE_NORMAL` - `RSA_MODE_CRT` - `RSA_MODE_CRTBYPASS` - `RSA_MODE_SCAP` - `RSA_MODE_CRT_SCAP` - `RSA_MODE_CRTBYPASS_SCAP` - `Src`:RSA DMA 來源數據。 - `n`:公私簽名的模數。 - `u32PNum`:CRT/SCAP 模式下模數操作因子 P 的編號。 - `u32QNum`:CRT/SCAP 模式下模數操作因子 Q 的編號。 - `u32CpNum`:CRT 模式下的 CP 編號。 - `u32CqNum`:CRT 模式下的 Cq 編號。 - `u32DpNum`:CRT 模式下的 Dp 編號。 - `u32DqNum`:CRT 模式下的 Dq 編號。 - `u32RpNum`:CRT 模式下的 Rp 編號。 - `u32RqNum`:CRT 模式下的 Rq 編號。 - **返回值**: - `0`:成功。 - `-1`:RSA 坐標體的指針為空。 - sample - ```c ... if(RSA_Open(CRPT, RSA_MODE_NORMAL, RSA_KEY_SIZE_2048, &s_sRSABuf, sizeof(s_sRSABuf), 0) != 0) { printf("\nRSA buffer size is incorrect!!\n"); return -1; } /* Set RSA private key */ RSA_SetKey(CRPT, d); RSA_SetDMATransfer(CRPT, Msg, N, 0, 0); RSA_Start(CRPT); /* Waiting for RSA operation done */ u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */ while(!g_RSA_done) { if(--u32TimeOutCnt == 0) { printf("Wait for RSA operation done time-out!\n"); return -1; } } /* Check error flag */ if(g_RSA_error) { printf("\nRSA has error!!\n"); return -1; } /* Get RSA output result */ RSA_Read(CRPT, OutputResult); printf("\nRSA sign: %s\n", OutputResult); ... ``` ## UART ### Introduction **UART 基本概念:** 1. **UART** - UART 代表通用非同步收發器。 - 它是一種用於串行數據通信的硬體電路或獨立 IC。 2. **UART 用途:** - 用於將數據在不同設備之間進行串行通信。 - 常見於DIY電子項目,如與Raspberry Pi、Arduino或其他微控制器連接GPS模塊、藍牙模塊和RFID卡讀卡器模塊。 3. **UART 通信基本原理:** - 使用兩根電線(Tx和Rx)在兩個UART之間傳輸數據。 - 數據從傳送UART的Tx引腳流向接收UART的Rx引腳。 **UART 通信的詳細信息:** 4. **非同步通信:** - UART 是非同步通信,無需時鐘信號同步傳輸。 - 起始位和停止位用於定義數據包的開始和結束,以便接收UART知道何時開始讀取位元。 5. **鮑率(Baud Rate):** - 鮑率是數據傳輸速度的度量,以位元每秒(bps)表示。 - 傳送和接收UART必須以大致相同的鮑率運行。 6. **數據包結構:** - UART傳輸的數據組織成數據包。 - 數據包包括起始位、5到9個數據位(取決於UART)、可選的奇偶校驗位和1或2個停止位。 7. **起始位(Start Bit):** - 用於開始數據傳輸,從高電壓轉換到低電壓。 8. **數據框(Data Frame):** - 包含實際傳輸的數據。 - 可以是5位到8位,如果使用奇偶校驗位則可以是9位。 9. **奇偶校驗位(Parity):** - 用於檢測傳輸期間數據是否更改的方式。 - 奇偶校驗位可確定1位的數據是否形成奇數或偶數。 10. **停止位(Stop Bits):** - 用於標識數據包的結束,通常為至少兩個位元。 **UART 的優點和缺點:** 11. **優點:** - 僅使用兩根電線。 - 無需時鐘信號。 - 具有奇偶校驗位,可用於錯誤檢查。 - 數據包結構可自定義,只要兩側都進行了設置。 - 獲得了廣泛的文檔和應用支援。 12. **缺點:** - 數據框大小受到最多9位的限制。 - 不支持多個從站或多個主站系統。 - 傳送和接收UART的鮑率必須在10%內。 **Flow control:** - 硬體流控制(CTS/RTS): - CTS (Clear to Send):CTS 是 Clear to Send 的縮寫,意為「允許發送」。CTS 訊號由接收方生成,用於通知發送方是否可以發送資料。當接收方有足夠的空間來接收更多數據多時,接收方設定CTS設定為有效,表示可以接受數據。這防止了發送方發送過多的數據,從而避免了數據遺失或遺失。 - RTS (Request to Send):RTS 是 Request to Send 的縮寫,為「請求」。RTS 訊號由傳送者產生,用於通知接收者要傳送資料。傳送者會在傳送資料之前檢查 RTS 訊號,如果RTS有效,則發送資料。這保證了資料只有在接收方準備好時才被發送。 - 在硬體流控制中,CTS和RTS是針對使用的,以確保雙方之間的資料傳輸是同步和協調的。這種流控制適用於高速通訊或雜訊環境下,因為它的反應速度較快,不依賴數據內容。 - 軟體流控制(Xon/Xoff): - 軟體流控制使用特殊的控製字元來指示資料流的開始和停止。它通常包括以下兩個字元: - Xon(Transmitter On):當接收方有足夠的空間來接收資料時,接收方發送 Xon 字符,表示發送方可以繼續發送資料。 - Xoff(Transmitter Off):當接收方要快滿時,接收方發送 Xoff 字符,表示發送方應該停止發送數據,直到接收方有足夠的空間。 - Xon/Xoff流控制主要用於低速通訊或雙方協商不支援硬體流控制的情況。它依賴於特殊的控製字符,因此在某些情況下可能會受到字符轉義或資料遺失的影響。 流量控制是確保串行通訊中資料可靠傳輸的重要機制。硬體流控制採用CTS和RTS訊號來實現,適用於高速通信,而軟體流控制採用Xon和Xoff字符,適用於低速通訊或不支援硬體流控制的情況。選擇哪種流控制方式通常取決於通訊環境和設備之間的協商。 ### Function in M2354 **用法:** - init ``` void UART1_Init(void) { /*---------------------------------------------------------------------------------------------------------*/ /* Init UART */ /*---------------------------------------------------------------------------------------------------------*/ /* Reset UART1 */ SYS_ResetModule(UART1_RST); /* Configure UART1 and set UART1 Baudrate */ UART_Open(UART1, 115200); /* Enable RDA and RTO Interrupt */ NVIC_EnableIRQ(UART1_IRQn); UART_EnableInt(UART1, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RLSIEN_Msk | UART_INTEN_RXTOIEN_Msk)); } ``` - interrupt ``` void UART1_IRQHandler(void) { uint8_t u8InChar = 0xFF; /* Rx Ready or Time-out INT */ if(UART_GET_INT_FLAG(UART1, UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) { /* Read data until RX FIFO is empty */ while(UART_GET_RX_EMPTY(UART1) == 0) { u8InChar = (uint8_t)UART_READ(UART1); g_u8RecData[g_i32Pointer++] = u8InChar; } } /* Handle transmission error */ if(UART1->FIFOSTS & (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk)) { UART1->FIFOSTS = (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk); } } ``` 1. **UART_ClearIntFlag**: - 作用:清除 UART 模組的特定中斷標誌。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32InterruptFlag`:要清除的中斷標誌,可以是以下之一或多個組合:Transmitter Empty Interrupt、Single-wire Bit Error Detect Interrupt、Auto-baud Rate Interrupt、Lin Bus interrupt、Wake-up interrupt、Buffer Error interrupt、Rx Time-out Interrupt、MODEM Status Interrupt、Receive Line Status Interrupt、Transmit Holding Register Empty Interrupt、Receive Data Available Interrupt。 - 返回值:無。 - 詳細:此函數可用於清除指定的 UART 中斷標誌,以便在中斷處理程序中使用。 2. **UART_Close**: - 作用:關閉 UART 模組,禁用中斷。 - 參數: - `uart`:指向 UART 模組的指針。 - 返回值:無。 - 詳細:此函數用於停用 UART,通常在結束 UART 通信時使用。 3. **UART_DisableFlowCtrl**: - 作用:禁用 UART 的自動流控制功能。 - 參數: - `uart`:指向 UART 模組的指針。 - 返回值:無。 - 詳細:自動流控制功能用於控制 UART 數據流的流入和流出,此函數禁用這些功能。 4. **UART_DisableInt**: - 作用:禁用 UART 的特定中斷。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32InterruptFlag`:要禁用的中斷,可以是以下之一或多個組合:Transmitter Empty Interrupt、Auto-baud Rate Interrupt、Lin Bus interrupt、Wake-up interrupt、Buffer Error interrupt、Rx Time-out Interrupt、MODEM Status Interrupt、Receive Line Status Interrupt、Transmit Holding Register Empty Interrupt、Receive Data Available Interrupt。 - 返回值:無。 - 詳細:此函數用於禁用指定的 UART 中斷,以停止相應的中斷處理程序。 5. **UART_EnableFlowCtrl**: - 作用:啟用 UART 的自動流控制功能。 - 參數: - `uart`:指向 UART 模組的指針。 - 返回值:無。 - 詳細:自動流控制功能用於控制 UART 數據流的流入和流出,此函數啟用這些功能,通常用於控制數據流的流動。 6. **UART_EnableInt**: - 作用:啟用 UART 的特定中斷。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32InterruptFlag`:要啟用的中斷,可以是以下之一或多個組合:Transmitter Empty Interrupt、Auto-baud Rate Interrupt、Lin Bus interrupt、Wake-up interrupt、Buffer Error interrupt、Rx Time-out Interrupt、MODEM Status Interrupt、Receive Line Status Interrupt、Transmit Holding Register Empty Interrupt、Receive Data Available Interrupt。 - 返回值:無。 - 詳細:此函數用於啟用指定的 UART 中斷,以允許相應的中斷處理程序執行。 7. **UART_Open**: - 作用:開啟 UART 功能並設定波特率和其他通信參數。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32baudrate`:設定的波特率。 - 返回值:無。 - 詳細:此函數用於初始化並啟用 UART 模組,並設定通信參數,例如波特率、數據位寬、奇偶校驗和停止位數。 8. **UART_Read**: - 作用:從 UART 接收緩衝區中讀取數據,並將其存儲在指定的緩衝區中。 - 參數: - `uart`:指向 UART 模組的指針。 - `pu8RxBuf`:用於存儲接收數據的緩衝區。 - `u32ReadBytes`:要讀取的字節數。 - 返回值:實際接收到的字節數。 - 詳細:此函數用於從 UART 接收緩衝區讀取數據,直到指定的字節數被讀取完畢。它將等待接收完成。 9. **UART_SetLineConfig**: - 作用:設置 UART 線路配置,包括波特率、數據位寬、奇偶校驗和停止位數。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32baudrate`:設定的波特率。如果為0,則不更改波特率。 - `u32data_width`:數據位寬,可以是 5、6、7 或 8 位。 - `u32parity`:奇偶校驗模式,可以是無校驗、奇校驗、偶校驗、標記校驗或空格校驗。 - `u32stop_bits`:停止位數,可以是 1、1.5 或 2 位。 - 返回值:無。 - 詳細:此函數用於設置 UART 的通信參數,包括波特率、數據位寬、奇偶校驗和停止位數。 10. **UART_SetTimeoutCnt**: - 作用:設置 UART 接收超時計數器的值,用於檢測接收超時。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32TOC`:接收超時計數器的值。 - 返回值:無。 - 詳細:此函數用於設置 UART 接收超時計數器的值,如果接收數據的時間超過此計數器的值,則引發接收超時中斷。 11. **UART_SelectIrDAMode**: - 作用:選擇並配置 UART 的紅外數據傳輸模式(IrDA)。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32Buadrate`:IrDA 模式的波特率。 - `u32Direction`:IrDA 方向,可以是發送(TXEN)或接收(RXEN)。 - 返回值:無。 - 詳細:此函數用於選擇 IrDA 模式並設置相關參數,例如波特率和數據方向。 12. **UART_SelectRS485Mode**: - 作用:選擇並配置 UART 的 RS485 模式。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32Mode`:RS485 操作模式,可以是 NMM(通常多主機模式)、AUD(自動位址偵測模式)或 AAD(自動位址偵測模式)。 - `u32Addr`:RS485 地址,用於自動位址偵測模式。 - 返回值:無。 - 詳細:此函數用於選擇 RS485 模式並配置相關參數,例如操作模式和地址。 13. **UART_SelectLINMode**: - 作用:選擇並配置 UART 的 LIN(局域網互聯網)模式。 - 參數: - `uart`:指向 UART 模組的指針。 - `u32Mode`:LIN 操作模式,可以是主機模式或從機模式。 - 返回值:無。 - 詳細:此函數用於選擇 LIN 模式並配置相關的操作模式。 14. **UART_Write** 函数: - 功能:将数据写入 UART 发送缓冲区以通过 UART 传输数据。 - 参数: - `uart`:指向指定 UART 模块的指针。 - `pu8TxBuf`:包含要发送到 UART 传输 FIFO 的数据的缓冲区。 - `u32WriteBytes`:要传输的字节数。 - 返回值:返回实际传输的字节数。 - 详细:此函数用于将数据写入 UART 的发送缓冲区,以便通过 UART 传输。它会不断检查 UART 的发送缓冲区是否已满,如果满了,则等待缓冲区可用。如果在等待时达到了一个时间上限(0x40000000ul),函数将退出,否则将数据写入缓冲区。函数会返回实际传输的字节数。 15. **UART_SelectSingleWireMode** 函数: - 功能:用于选择 UART 单线模式。 - 参数: - `uart`:指向指定 UART 模块的指针。 - 返回值:无。 - 详细:此函数用于配置 UART 为单线模式。单线模式通常用于特殊应用,其中只有一个线路用于同时发送和接收数据。函数通过设置 UART 的 FUNCSEL 寄存器来选择单线模式。 ## Sentry ### Secure partition (set Non-Secure) - Peripheral Secure Attribution Configuration - TIMER - TMR23 - UART - UART0 - UART1 ### Data Transmit #### Init - Authenticator ![image.png](https://hackmd.io/_uploads/r1j1mwJ7p.png)| - Qx1, Qy1, d1 are generated by ECC - Sentry 1. 使用 FMC_Read 檢查目前狀態 2. ECC產生並儲存裝置的金鑰對,將公鑰儲存在全域變數 OwnerPk_x 和 OwnerPk_y 中。 3. 使用特定的API將公鑰寫入金鑰儲存區(key store),同時也在快閃記憶體中儲存了對應的索引。 4. 執行一些測試操作,例如測試快閃記憶體以及金鑰讀取操作 #### Query - Authenticator ![image.png](https://hackmd.io/_uploads/HyWKuwyX6.png) - Sentry ![image.png](https://hackmd.io/_uploads/Hyt1tv1Qp.png) #### Management - Authenticator ![image.png](https://hackmd.io/_uploads/HJc2Yw1X6.png) - Qx2 and Qy2 are generated by ECC again as a second user - d is d1 - Sentry ![image.png](https://hackmd.io/_uploads/rJu6cwk7T.png) - Ownership_Transfer 將key store 裡的資料換掉 #### ACCESS - Authenticator 1. ![image.png](https://hackmd.io/_uploads/H1Ho6vJ76.png) -` PermissionTable door_permission = {.open_door = TRUE,.close_door = TRUE,.door_log = TRUE};` 2. ![image.png](https://hackmd.io/_uploads/ByOpxd1m6.png) 3. 認證Keyexc ticket with ECC ->若認證成功可以做交互 - Sentry 1. ``` /* First check if the owner's signature is on the ticket */ if ( Verify_Owner_Signature(tktptr) ) return 1; /* Extract the command recorded on the ticket */ strcpy(command,tktptr->request_body); if ( Challenge_User(tktptr) ) return 1; return 0; ``` - Challenge_User will send a challenge ticket to Authenticator![image.png](https://hackmd.io/_uploads/S1oNxdkQp.png) 2. - 檢查請求體中的挑戰(challenge)是否User_Challenge相同,如果不同,則顯示錯誤訊息並傳回1,可能表示請求體中的挑戰不符。 - 驗證使用者的簽章(signature)是否有效,透過呼叫Verify_Signature函數,如果驗證失敗,則傳回1。 - 從金鑰儲存讀取中PRIVATEKEY_KSID的Sk(私人金鑰),然後使用ECC(橢圓形加密)的ECC_GenerateSecretZ函數產生共用金鑰shared_key,此共用金鑰將用於後續加密通訊。如果產生失敗,會顯示錯誤訊息並返回1。 - ![image.png](https://hackmd.io/_uploads/Hy0xQd1QT.png) 3. 等待交互 # 密碼學 ## 對稱式加密 vs. 非對稱式加密 ### 對稱式加密: - 使用相同的密鑰進行加密和解密。 - 密鑰在加密和解密過程中扮演關鍵角色。 - 明文(原始訊息)經過密鑰加密變為密文。 - 密文經過同一密鑰解密還原為明文。 - 加密速度較快,適用於大量資料的加密。 - 存在密鑰分發風險,傳遞密鑰需要保證安全性。 ### 非對稱式加密(公鑰加密): - 使用不同的公鑰和私鑰進行加密和解密。 - 公鑰用於加密,私鑰用於解密。 - 公鑰可以公開分享,私鑰需要保密。 - 明文經過公鑰加密變為密文。 - 密文經過私鑰解密還原為明文。 - 安全性較高,私鑰是保護資料的關鍵。 - 加密速度較慢,適用於少量重要資料的保護。 ### 比較: - 對稱式加密: - 使用相同的密鑰進行加密和解密。 - 加密速度較快。 - 存在密鑰分發風險。 - 非對稱式加密: - 使用不同的公鑰和私鑰進行加密和解密。 - 安全性較高,私鑰保護重要資料。 - 公鑰可以公開分享,私鑰需要保密。 - 加密速度較慢。 ## 加密模式(mode of operation) ### ECB(Electronic CodeBook)電子密碼本模式 - 每個分組使用相同的金鑰進行加密。 - 相同明文對應相同密文,模式不隱藏資料特性。 - 優點:簡單易實做。 - 缺點:容易被偵測,重複性容易被辨識。 ### CBC(Cipher Block Chaining)密碼分組連結模式 - 引入初始化向量(IV)以隨機化加密過程。 - 前一密文影響後一分組的加密運算。 - 容易並行運算,提升效率。 - 優點:不同密文對應不同明文,加密器具有新狀態。 - 缺點:一密文錯誤影響多明文,初始向量易被攻擊。 ### CFB(Cipher Feedback)密文反饋模式 - 類似CBC,但密文影響密碼字典的生成。 - 支援即時通訊、自同步,適合流式資料。 - 優點:支援即時通訊,解密不增長,支援自同步。 - 缺點:錯誤增長問題,不宜於雜訊情況。 --- 詳細步驟 ![](https://hackmd.io/_uploads/BJjhYJZ3n.png) - 初始化 - 選擇適當的分組加密算法(如AES)和金鑰。 - 選擇初始向量(IV),IV的長度通常與分組大小相同。 - 生成密碼字典(Cipher Feedback Dictionary) - 使用金鑰和初始向量進行分組加密,得到初始的密碼字典。 - 密碼字典是一串位元,通常等於分組大小,可以想像它是一個加密的隨機位元序列。 - 加密過程 - 將明文按位元逐一加密。 - 將明文的位元與密碼字典的對應位元進行異或(XOR)運算,得到密文的對應位元。 - 將得到的密文位元加入到密碼字典的末尾,形成新的密碼字典。 - 重複上述步驟,逐位地對明文進行加密,得到對應的密文。 - 解密過程 - 同樣,將密文按位元逐一解密。 - 將密文的位元與密碼字典的對應位元進行異或運算,得到明文的對應位元。 - 將得到的明文位元加入到密碼字典的末尾,形成新的密碼字典。 - 重複上述步驟,逐位地對密文進行解密,得到對應的明文。 --- ### OFB(Output Feedback)輸出反饋模式 - 類似CFB,但使用明文參與加密金鑰生成。 - 支援即時通訊,避免錯誤增長。 - 優點:支援即時通訊,解密不增長,支援自同步。 - 缺點:需保持同步,IV不可重複使用。 ### CTR(Counter)計數器模式 - 利用計數器作為加密金鑰。 - 可以平行運算,支援即時通訊。 - 需要保持同步,避免錯誤增長。 - 優點:平行運算,支援即時通訊,支援隨機訪問。 - 缺點:需保持同步,IV不可重複使用。 ### CCM(Counter with CBC-MAC) - 結合CTR和CMAC認證演算法。 - 同時提供加密和完整性校驗。 ### GCM(Galois/Counter Mode) - 結合CTR和GHASH的組合,高並行度。 - 提供加密、完整性校驗和附加消息校驗。 ### 初始向量(IV)的作用與注意事項 用於隨機化和混淆加密模式。 防止相同明文分組得到相同密文。 初始向量不需要保密,但不應重複使用,以避免安全性問題。 ## AES(Advanced Encryption Standard) ### AES的基本結構 - AES加密過程基於一系列的步驟,分為四個主要步驟:SubBytes、ShiftRows、MixColumns和AddRoundKey。 - SubBytes: 使用S盒替換矩陣中的每個字節。S盒是一個非線性的查找表,用於字節的混淆。 - ShiftRows: 對矩陣的行進行循環位移。第一行不變,第二行右移1個位置,第三行右移2個位置,第四行右移3個位置。 - MixColumns: 對矩陣的每一列進行混淆操作。這涉及到矩陣運算,增加了密文的混淆程度。 - AddRoundKey: 使用輪密鑰對矩陣進行位元運算。輪密鑰是由主密鑰擴展生成的,每輪使用不同的輪密鑰。 ### 密鑰擴展 - AES使用輪密鑰來支持多輪的加密過程。這需要從主密鑰生成一系列的輪密鑰。 - 密鑰擴展算法使用主密鑰生成每輪所需的輪密鑰。 - 常見的AES密鑰長度為128位、192位和256位,不同長度的密鑰導致不同輪數。 ### 多輪AES加密過程 - AES加密過程通常包括初始輪、中間輪和最終輪。 - 初始輪: 包括AddRoundKey,使用初始輪密鑰對矩陣進行位元運算。 - 中間輪: 進行多輪的SubBytes、ShiftRows、MixColumns和AddRoundKey步驟,輪數取決於密鑰長度。 - 最終輪: 不執行MixColumns步驟,只執行SubBytes、ShiftRows和AddRoundKey。 ### 安全性和攻擊 - AES的安全性基於其密鑰長度和抵抗不同攻擊的能力。 - 可能的攻擊包括差分攻擊、線性攻擊等,但AES的密鑰長度足夠長時,這些攻擊難度很高。 ### 實際應用與實現 - AES被廣泛應用於數據庫加密、網絡通信和存儲保護等領域。 - 可以使用多種編程語言實現AES,確保密鑰的安全管理和加密的正確實施。 ## SHA(Secure Hash Algorithm) - **SHA是什麼:** - 安全雜湊算法(Secure Hash Algorithm)用於將任意長度的輸入資料轉換成固定長度的雜湊值。 - 主要用於確保數據完整性和驗證。 - **特點:** 1. **不可逆性:** 雜湊值無法反向推導出原始輸入資料。 2. **固定長度輸出:** 不論輸入資料大小,SHA生成固定長度的雜湊值。 3. **雜湊碰撞:** 可能存在相同雜湊值對應於不同輸入資料的情況,但現代SHA算法極難出現這種情況。 4. **安全性:** 安全性取決於防止碰撞和其他攻擊的能力。 - **應用領域:** - **數字簽名:** SHA用於生成數字簽名,確保文件的完整性和來源認證。 - **密碼學:** 用於生成安全雜湊密碼,確保密碼不會以明文儲存。 - **數位證書:** 用於生成證書指紋,驗證證書的真實性。 - **常見的SHA版本:** 1. **SHA-1:** 較早版本,存在碰撞風險,已不推薦使用。 2. **SHA-256、SHA-512等:** 較新版本,提供更高的安全性,廣泛應用。 - **計算SHA雜湊值的步驟:** 1. 接收輸入資料。 2. 使用SHA算法計算雜湊值。 3. 得到固定長度的雜湊值。 - **使用情境:** - 網路傳輸:驗證下載的文件是否未被更改。 - 數位簽名:確保文件的完整性和真實性。 - 密碼存儲:將密碼轉換成不可逆的雜湊值以增強安全性。 - **重要性:** - SHA算法對於數據保護和確保資料的可靠性至關重要。 - 它幫助我們確保數據在傳輸和儲存過程中不被意外或惡意地更改。 ## HMAC(Hash-based Message Authentication Code) - **HMAC是什麼:** - HMAC代表Hash-based Message Authentication Code。 - 它是一種用於驗證訊息完整性和真實性的訊息驗證碼。 - **用途:** - 主要用於確保發送或接收的訊息在傳輸過程中未被篡改。 - **特點:** 1. **基於雜湊函式:** HMAC使用一個安全雜湊函式來產生訊息的驗證碼。 2. **密鑰:** 它需要一個秘密金鑰,只有知道該金鑰的人才能生成和驗證HMAC。 3. **不對稱性:** 雖然使用單向雜湊函式,但HMAC提供了訊息的雙向驗證能力。 - **計算HMAC的步驟:** 1. 接收訊息和密鑰。 2. 使用雜湊函式(如SHA-256)將訊息和密鑰混合計算雜湊值。 3. 雜湊值即為HMAC。 - **優點:** - 提供了可靠的訊息完整性驗證,即使敵對方能查看訊息和HMAC。 - 需要密鑰,增加了訊息的保密性。 - **應用領域:** - **網路通訊:** 在網際網路通訊中確保數據未被篡改。 - **API驗證:** 用於確保API請求和回應的完整性。 - **數位簽名:** HMAC也可以用於產生數位簽名,以驗證文件的來源和完整性。 - **注意事項:** - 雖然HMAC提供了良好的訊息完整性保護,但仍然需要適當的安全實踐。 - 密鑰的保管至關重要,不應公開。 ## RSA(Rivest–Shamir–Adleman) - **RSA是什麼:** - RSA是一種非對稱加密算法,由Rivest、Shamir和Adleman三位數學家於1977年共同發明。 - 在數學和計算上基於質數分解難題。 - - RSA使用兩個密鑰:公鑰(用於加密)和私鑰(用於解密)。 - 公鑰可以自由分享,私鑰必須保密。 - **總類:** - RSA_MODE_NORMAL: 正常的RSA加密模式,根據標準的RSA算法進行操作。 - RSA_MODE_CRT: 使用中國剩餘定理(Chinese Remainder Theorem,CRT)的RSA加密模式,這種模式可以提高加密和解密的效能。 - RSA_MODE_CRTBYPASS: 使用CRT但不做CRT效能優化的RSA加密模式。 - RSA_MODE_SCAP: 使用Side-Channel Attack Protected(SCAP)的RSA加密模式,用於抵抗側信道攻擊。 - RSA_MODE_CRT_SCAP: 同時使用CRT和SCAP的RSA加密模式。 - RSA_MODE_CRTBYPASS_SCAP: 同時使用CRTBYPASS和SCAP的RSA加密模式。 - **加密過程:** 1. 接收者生成一對RSA金鑰(公鑰和私鑰)。 2. 發送者使用接收者的公鑰加密訊息。 3. 接收者使用私鑰解密訊息。 - **數位簽名:** - RSA也可以用於生成數位簽名,用於驗證文件的完整性和來源。 - **安全性:** - 安全性基於大質數的質因數分解問題,經過足夠長的金鑰長度,攻擊者難以有效地進行破解。 - **速度:** - 加解密運算速度較慢,尤其對於大型資料。 - **應用領域:** - **數位簽名:** 用於確保文件的來源和完整性。 - **加密通訊:** 用於保護敏感資訊的傳輸。 - **數位證書:** 用於在網際網路上建立信任。 - **注意事項:** - 較長的金鑰提供更高的安全性,但也會增加計算成本。 - RSA不應該用於加密大量資料,而是用於安全性要求較高的小型數據。 這些條列式筆記總結了RSA(Rivest–Shamir–Adleman)的基本概念、特點、應用和注意事項。 ### M2354 - 使用mbedTLS函式庫來實現AES加密。 - 初始化 ![](https://hackmd.io/_uploads/BkdG5J-22.png) - 設置密鑰 ![](https://hackmd.io/_uploads/HyB99J-2n.png) - 進行解密或加密 ![](https://hackmd.io/_uploads/r1oncy-hh.png) ###### tags: `Templates` `Book`