

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

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

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

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


**使用案例**  

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

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

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

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

corePKCS11 程式庫包含以軟體為基礎的 PKCS \$111 介面 (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\$1PAL\$1Initialize |  初始化 PAL 層。由 corePKCS11 程式庫在初始化序列開始時呼叫。  | 
| PKCS11\$1PAL\$1SaveObject |  將資料寫入非揮發性儲存。  | 
| PKCS11\$1PAL\$1FindObject |  使用 PKCS \$111 `CKA_LABEL` 在非揮發性儲存中搜尋對應的 PKCS \$111 物件，並傳回該物件的控制代碼 (如果存在)。  | 
| PKCS11\$1PAL\$1GetObjectValue |  根據控制代碼擷取物件的值。  | 
| PKCS11\$1PAL\$1GetObjectValueCleanup |  清除 `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 \$111 的 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，以驗證 cryptoki 操作結果。
+ `RunQualificationTest()` 從應用程式呼叫 。

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

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


**PKSC11 測試組態**  

| 組態 | 描述 | 
| --- | --- | 
| PKCS11\$1TEST\$1RSA\$1KEY\$1SUPPORT |  移植支援 RSA 金鑰函數。  | 
| PKCS11\$1TEST\$1EC\$1KEY\$1SUPPORT |  移植支援 EC 金鑰函數。  | 
| PKCS11\$1TEST\$1IMPORT\$1PRIVATE\$1KEY\$1SUPPORT |  移植支援匯入私有金鑰。如果啟用支援金鑰函數，則測試中會驗證 RSA 和 EC 金鑰匯入。  | 
| PKCS11\$1TEST\$1GENERATE\$1KEYPAIR\$1SUPPORT |  移植支援金鑰對產生。如果啟用支援金鑰函數，EC keypair 產生會在測試中驗證。  | 
| PKCS11\$1TEST\$1PREPROVISIONED\$1SUPPORT |  移植有預先佈建的登入資料。 `PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS``PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS`和 `PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS`是登入資料的範例。  | 
| PKCS11\$1TEST\$1LABEL\$1DEVICE\$1PRIVATE\$1KEY\$1FOR\$1TLS |  測試中使用的私有金鑰標籤。  | 
| PKCS11\$1TEST\$1LABEL\$1DEVICE\$1PUBLIC\$1KEY\$1FOR\$1TLS |  測試中使用的公有金鑰標籤。  | 
| PKCS11\$1TEST\$1LABEL\$1DEVICE\$1CERTIFICATE\$1FOR\$1TLS |  測試中使用的憑證標籤。  | 
| PKCS11\$1TEST\$1JITP\$1CODEVERIFY\$1ROOT\$1CERT\$1SUPPORTED |  移植支援 JITP 儲存。將此設定為 1 以啟用 JITP `codeverify`測試。  | 
| PKCS11\$1TEST\$1LABEL\$1CODE\$1VERIFICATION\$1KEY |  JITP `codeverify`測試中使用的程式碼驗證金鑰標籤。  | 
| PKCS11\$1TEST\$1LABEL\$1JITP\$1CERTIFICATE |  JITP `codeverify`測試中使用的 JITP 憑證標籤。  | 
| PKCS11\$1TEST\$1LABEL\$1ROOT\$1CERTIFICATE |  JITP `codeverify`測試中使用的根憑證標籤。  | 

FreeRTOS 程式庫和參考整合必須至少支援一個金鑰函數組態，例如 RSA 或橢圓曲線金鑰，以及一個 PKCS11 APIs支援的金鑰佈建機制。測試必須啟用下列組態：
+ 至少下列其中一個金鑰函數組態：
  + PKCS11\$1TEST\$1RSA\$1KEY\$1SUPPORT
  + PKCS11\$1TEST\$1EC\$1KEY\$1SUPPORT
+ 至少下列其中一個金鑰佈建組態：
  + PKCS11\$1TEST\$1IMPORT\$1PRIVATE\$1KEY\$1SUPPORT
  + PKCS11\$1TEST\$1GENERATE\$1KEYPAIR\$1SUPPORT
  + PKCS11\$1TEST\$1PREPROVISIONED\$1SUPPORT 

預先佈建的裝置登入資料測試必須在下列條件下執行：
+ `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_CERTIFICATE_FOR_TLS`會銷毀具有標籤 `PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_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\$1PKCS11\$1TEST\$1ENABLED** `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 FreeRTOS](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 檔案中啟用正確的測試群組。