

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 移植 corePKCS11 程式庫
<a name="afr-porting-pkcs"></a>

公有金鑰密碼編譯標準 \#11 定義了與平台無關的 API，以管理和使用密碼編譯字符。[PKCS 11](https://en.wikipedia.org/wiki/PKCS_11) 是指標準及其定義的 APIs。PKCS \#11 密碼編譯 API 會抽象金鑰儲存、密碼編譯物件的 get/set 屬性，以及工作階段語意。它廣泛用於操縱常見的密碼編譯物件。其 函數允許應用程式軟體使用、建立、修改和刪除密碼編譯物件，而不會將這些物件暴露到應用程式的記憶體。

FreeRTOS 程式庫和參考整合使用 PCKS \#11 介面標準的子集，著重於涉及非對稱金鑰、隨機數量產生和雜湊的操作。下表列出要支援的使用案例和所需的 PKCS \#11 APIs。


**使用案例**  

| 使用案例 | 必要的 PKCS \#11 API 系列 | 
| --- | --- | 
| 全部 | 初始化、完成、開啟/關閉工作階段、GetSlotList、登入 | 
| 佈建中 | GenerateKeyPair、CreateObject、DestroyObject、InitToken、GetTokenInfo | 
| TLS | Random、Sign、FindObject、GetAttributeValue | 
| FreeRTOS\+TCP | 隨機、摘要 | 
| OTA | Verify、Digest、FindObject、GetAttributeValue | 

## 何時實作完整的 PKCS \#11 模組
<a name="implemeting-pkcs"></a>

在評估和快速原型設計案例中，將私有金鑰存放在一般用途快閃記憶體中可能很方便。我們建議您使用專用密碼編譯硬體，以減少生產案例中資料遭竊和裝置重複的威脅。密碼編譯硬體包含的元件有功能可防止匯出密碼編譯私密金鑰。若要支援此功能，您必須實作使用 FreeRTOS 程式庫所需的 PKCS \#11 子集，如上表所定義。

## 何時使用 FreeRTOS corePKCS11
<a name="using-pkcs"></a>

corePKCS11 程式庫包含以軟體為基礎的 PKCS \#11 介面 (API) 實作，其使用 [Mbed TLS ](https://tls.mbed.org/)提供的密碼編譯功能。這適用於硬體沒有專用密碼編譯硬體的快速原型設計和評估案例。在此情況下，您只需要實作 corePKCS11 PAL 即可讓 corePKCS11 軟體型實作與硬體平台搭配使用。

## 移植 corePKCS11
<a name="porting-core-pkcs"></a>

您必須擁有將密碼編譯物件讀取和寫入非揮發性記憶體 (NVM) 的實作，例如內建快閃記憶體。密碼編譯物件必須存放在未初始化的 NVM 區段中，且不會在裝置重新程式設計時清除。corePKCS11 程式庫的使用者將使用登入資料佈建裝置，然後使用透過 corePKCS11 界面存取這些登入資料的新應用程式來重新程式設計裝置。corePKCS11 PAL 連接埠必須提供要存放的位置：
+ 裝置用戶端憑證
+ 裝置用戶端私有金鑰
+ 裝置用戶端公有金鑰
+ 信任的根 CA
+ 用於安全開機載入器和over-the-air(OTA) 更新的程式碼驗證公有金鑰 （或包含程式碼驗證公有金鑰的憑證）
+ Just-In-Time佈建憑證

包含 [標頭檔案](https://github.com/FreeRTOS/corePKCS11/blob/main/source/include/core_pkcs11_pal.h)並實作定義的 PAL APIs。


**PAL APIs**  

| 函式 | 說明 | 
| --- | --- | 
| PKCS11\_PAL\_Initialize | 初始化 PAL 層。在初始化序列開始時，由 corePKCS11 程式庫呼叫。 | 
| PKCS11\_PAL\_SaveObject | 將資料寫入非揮發性儲存。 | 
| PKCS11\_PAL\_FindObject | 使用 PKCS \#11 `CKA_LABEL` 在非揮發性儲存中搜尋對應的 PKCS \#11 物件，並傳回該物件的控制代碼 (如果存在)。 | 
| PKCS11\_PAL\_GetObjectValue | 根據控制代碼擷取物件的值。 | 
| PKCS11\_PAL\_GetObjectValueCleanup | 清除 `PKCS11_PAL_GetObjectValue` 呼叫。可用於釋放 `PKCS11_PAL_GetObjectValue` 呼叫中配置的記憶體。 | 

## 測試
<a name="porting-testing-pkcs"></a>

如果您使用 FreeRTOS corePKCS11 程式庫或實作所需的 PKCS11 APIs 子集，您必須通過 FreeRTOS PKCS11 測試。這些測試 FreeRTOS 程式庫所需的函數是否如預期般執行。

本節也說明如何使用資格測試在本機執行 FreeRTOS PKCS11 測試。

### 先決條件
<a name="porting-testing-prereqs"></a>

若要設定 FreeRTOS PKCS11 測試，必須實作下列項目。
+ PKCS11 APIs支援的連接埠。
+ FreeRTOS 資格測試平台函數的實作，包括下列項目：
  + `FRTest_ThreadCreate`
  + `FRTest_ThreadTimedJoin`
  + `FRTest_MemoryAlloc`
  + `FRTest_MemoryFree`

（請參閱 GitHub [上 PKCS \#11 的 FreeRTOS 程式庫整合測試的 README.md](https://github.com/FreeRTOS/FreeRTOS-Libraries-Integration-Tests/tree/main/src/pkcs11) 檔案。) FreeRTOS GitHub.)

### 移植測試
<a name="porting-tests-pkcs11"></a>
+ 將 [ FreeRTOS-Libraries-Integration-Tests](https://github.com/FreeRTOS/FreeRTOS-Libraries-Integration-Tests/tree/main/src/pkcs11) 作為子模組新增至您的專案。子模組可以放置在專案的任何目錄中，只要可以建置即可。
+ 將 `config_template/test_execution_config_template.h`和 `config_template/test_param_config_template.h` 複製到建置路徑中的專案位置，並將其重新命名為 `test_execution_config.h`和 `test_param_config.h`。
+ 在建置系統中包含相關檔案。如果使用 `CMake`， `qualification_test.cmake`和 `src/pkcs11_tests.cmake`可用來包含相關檔案。
+ 實作 ，`UNITY_OUTPUT_CHAR`讓測試輸出日誌和裝置日誌不會交錯。
+ 整合 MbedTLS，以驗證加密操作結果。
+ `RunQualificationTest()` 從應用程式呼叫 。

### 設定測試
<a name="configure-pkcs11-tests"></a>

PKCS11 測試套件必須根據 PKCS11 實作進行設定。下表列出 `test_param_config.h`標頭檔案中 PKCS11 測試所需的組態。


**PKSC11 測試組態**  

| Configuration | 說明 | 
| --- | --- | 
| PKCS11\_TEST\_RSA\_KEY\_SUPPORT | 移植支援 RSA 金鑰函數。 | 
| PKCS11\_TEST\_EC\_KEY\_SUPPORT | 移植支援 EC 金鑰函數。 | 
| PKCS11\_TEST\_IMPORT\_PRIVATE\_KEY\_SUPPORT | 移植支援匯入私有金鑰。如果啟用支援金鑰函數，則會在測試中驗證 RSA 和 EC 金鑰匯入。 | 
| PKCS11\_TEST\_GENERATE\_KEYPAIR\_SUPPORT | 移植支援金鑰對產生。如果啟用支援金鑰函數，則會在測試中驗證 EC 金鑰對產生。 | 
| PKCS11\_TEST\_PREPROVISIONED\_SUPPORT | 移植有預先佈建的登入資料。 `PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS``PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS`和 `PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS`是登入資料的範例。 | 
| PKCS11\_TEST\_LABEL\_DEVICE\_PRIVATE\_KEY\_FOR\_TLS | 測試中使用的私有金鑰標籤。 | 
| PKCS11\_TEST\_LABEL\_DEVICE\_PUBLIC\_KEY\_FOR\_TLS | 測試中使用的公有金鑰標籤。 | 
| PKCS11\_TEST\_LABEL\_DEVICE\_CERTIFICATE\_FOR\_TLS | 測試中使用的憑證標籤。 | 
| PKCS11\_TEST\_JITP\_CODEVERIFY\_ROOT\_CERT\_SUPPORTED | 移植支援 JITP 儲存。將此設定為 1 以啟用 JITP `codeverify`測試。 | 
| PKCS11\_TEST\_LABEL\_CODE\_VERIFICATION\_KEY | JITP `codeverify`測試中使用的程式碼驗證金鑰標籤。 | 
| PKCS11\_TEST\_LABEL\_JITP\_CERTIFICATE | JITP `codeverify`測試中使用的 JITP 憑證標籤。 | 
| PKCS11\_TEST\_LABEL\_ROOT\_CERTIFICATE | JITP `codeverify`測試中使用的根憑證標籤。 | 

FreeRTOS 程式庫和參考整合必須至少支援一個金鑰函數組態，例如 RSA 或橢圓曲線金鑰，以及 PKCS11 APIs 支援的一個金鑰佈建機制。測試必須啟用下列組態：
+ 至少下列其中一個金鑰函數組態：
  + PKCS11\_TEST\_RSA\_KEY\_SUPPORT
  + PKCS11\_TEST\_EC\_KEY\_SUPPORT
+ 至少下列其中一個金鑰佈建組態：
  + PKCS11\_TEST\_IMPORT\_PRIVATE\_KEY\_SUPPORT
  + PKCS11\_TEST\_GENERATE\_KEYPAIR\_SUPPORT
  + PKCS11\_TEST\_PREPROVISIONED\_SUPPORT 

預先佈建的裝置登入資料測試必須在下列條件下執行：
+ `PKCS11_TEST_PREPROVISIONED_SUPPORT` 必須啟用 ，並停用其他佈建機制。
+ 僅`PKCS11_TEST_EC_KEY_SUPPORT`啟用一個金鑰函數， `PKCS11_TEST_RSA_KEY_SUPPORT`或 。
+ 根據您的金鑰函數設定預先佈建的金鑰標籤，包括 `PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS`、 `PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS`和 `PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS`。在執行測試之前，這些登入資料必須存在。

如果實作支援預先佈建的登入資料和其他佈建機制，則測試可能需要使用不同的組態執行數次。

**注意**  
如果 `PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT`或 已啟用`PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS`，則在測試期間`PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS`會銷毀具有標籤 、 `PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS`和 `PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT`的物件。

### 執行測試
<a name="running-tests"></a>

本節說明如何使用資格測試在本機測試 PKCS11 介面。或者，您也可以使用 IDT 自動化執行。如需詳細資訊[AWS IoT Device Tester ，請參閱FreeRTOS](https://docs.aws.amazon.com/freertos/latest/userguide/device-tester-for-freertos-ug.html) *使用者指南》中的 FreeRTOS*。

下列指示說明如何執行測試：
+ 開啟 **CORE\_PKCS11\_TEST\_ENABLED** `test_execution_config.h`並定義為 1。
+ 建置應用程式並刷新至您的裝置以執行。測試結果會輸出到序列連接埠。

以下是輸出測試結果的範例。

```
TEST(Full_PKCS11_StartFinish, PKCS11_StartFinish_FirstTest) PASS
TEST(Full_PKCS11_StartFinish, PKCS11_GetFunctionList) PASS
TEST(Full_PKCS11_StartFinish, PKCS11_InitializeFinalize) PASS
TEST(Full_PKCS11_StartFinish, PKCS11_GetSlotList) PASS
TEST(Full_PKCS11_StartFinish, PKCS11_OpenSessionCloseSession) PASS
TEST(Full_PKCS11_Capabilities, PKCS11_Capabilities) PASS
TEST(Full_PKCS11_NoObject, PKCS11_Digest) PASS
TEST(Full_PKCS11_NoObject, PKCS11_Digest_ErrorConditions) PASS
TEST(Full_PKCS11_NoObject, PKCS11_GenerateRandom) PASS
TEST(Full_PKCS11_NoObject, PKCS11_GenerateRandomMultiThread) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_CreateObject) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_FindObject) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_GetAttributeValue) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_Sign) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_FindObjectMultiThread) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_GetAttributeValueMultiThread) PASS
TEST(Full_PKCS11_RSA, PKCS11_RSA_DestroyObject) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_GenerateKeyPair) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_CreateObject) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_FindObject) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_GetAttributeValue) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_Sign) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_Verify) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_FindObjectMultiThread) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_GetAttributeValueMultiThread) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_SignVerifyMultiThread) PASS
TEST(Full_PKCS11_EC, PKCS11_EC_DestroyObject) PASS

-----------------------
27 Tests 0 Failures 0 Ignored
OK
```

 當所有測試都通過時，測試就完成。

**注意**  
若要正式讓裝置符合 FreeRTOS 的資格，您必須使用 驗證裝置的移植原始碼 AWS IoT Device Tester。請遵循 [ FreeRTOS 使用者指南中的使用 AWS IoT Device Tester for](https://docs.aws.amazon.com/freertos/latest/userguide/device-tester-for-freertos-ug.html) FreeRTOS 中的指示來設定 AWS IoT Device Tester 連接埠驗證。若要測試特定程式庫的連接埠，必須在 `configs` 資料夾中的 `device.json` 檔案中 AWS IoT Device Tester 啟用正確的測試群組。