diff --git a/wolfHSM/Makefile b/wolfHSM/Makefile index 5999612e..df0724c3 100644 --- a/wolfHSM/Makefile +++ b/wolfHSM/Makefile @@ -1,4 +1,11 @@ -include ../common/common.am + +ifeq ($(DOC_LANG),JA) + SRC = wolfhsm/docs/src-ja +else + SRC = wolfhsm/docs/src +endif + .DEFAULT_GOAL := all all: pdf html @@ -29,7 +36,11 @@ wolfhsm: .PHONY: wolfhsm-update wolfhsm-update: wolfhsm - $(Q)cd wolfhsm && git pull --ff-only + $(Q)if [ -L wolfhsm ]; then \ + echo "Skipping git pull for symlink (local testing)"; \ + else \ + cd wolfhsm && git pull --ff-only; \ + fi .PHONY: api api: wolfhsm-update @@ -38,6 +49,31 @@ api: wolfhsm-update $(Q)cd .. $(Q)doxybook2 --input docs/xml --output api/md --config doxybook.cfg +# NOTE: html-setup and pdf-setup are overridden from common/common.am to inject +# the wolfhsm-update dependency. If common.am changes these targets, the changes +# will need to be manually synchronized here. This duplication is intentional to +# ensure the wolfHSM repo is cloned before attempting to copy docs from it. + +# Override html-setup to ensure wolfhsm repo is cloned first +.PHONY: html-setup +html-setup: wolfhsm-update + $(Q)git submodule update --init + -cd ../mkdocs-material; patch -p1 < $(PATCH) --ignore-whitespace -N + $(Q)cp -a $(SRC)/* build/html/ + $(Q)cp ../common/*.png build/html/ + $(Q)cp ../common/*.css build/html/ + $(Q)perl -i -pe 's/ ```/```/g' build/html/*.md + $(Q)perl -i -pe "s/\#--/\#-/g" build/html/*.md + $(Q)mv build/html/$(word 1,$(SOURCES)) build/html/index.md + +# Override pdf-setup to ensure wolfhsm repo is cloned first +.PHONY: pdf-setup +pdf-setup: wolfhsm-update builddir + $(Q)cp -a $(SRC)/* build/pdf/ + $(Q)cp ../common/*.png build/pdf/ + $(Q)perl -i -pe "s/chapter[0-9][0-9].md|appendix[0-9][0-9].md//g" build/pdf/*.md + $(Q)perl -i -pe "s/\#--/\#/g" build/pdf/*.md + # Need an index.md, so let's make it chapter01. # Perl regex to fix two things: # 1. Doxybook2 replaces underscores with dashes in anchor tags (which breaks them) @@ -45,7 +81,6 @@ api: wolfhsm-update # 3. Fix the titles of the header files markdown .PHONY: html-prep html-prep: api - $(Q)cp src/*.png build/html/ $(Q)cp -a api/md/*8h* build/html/ $(Q)perl -i -pe "s/\/group_/group_/g" build/html/group* build/html/*8h* @@ -61,7 +96,6 @@ html-prep: api # 6. Two regexes to handle bad Doxygen that didn't convert and the LaTeX processor thinks is LaTeX commands .PHONY: pdf-prep pdf-prep: api - $(Q)cp src/*.png build/pdf/ $(Q)cp -a api/md/*8h* build/pdf/ $(Q)perl -i -pe "s/# /## /g" build/pdf/*.md diff --git a/wolfHSM/src-ja/appendix01.md b/wolfHSM/src-ja/appendix01.md deleted file mode 100644 index dbd77bb8..00000000 --- a/wolfHSM/src-ja/appendix01.md +++ /dev/null @@ -1 +0,0 @@ -# wolfHSM APIリファレンス diff --git a/wolfHSM/src-ja/chapter01.md b/wolfHSM/src-ja/chapter01.md deleted file mode 100644 index b00d6e7d..00000000 --- a/wolfHSM/src-ja/chapter01.md +++ /dev/null @@ -1,13 +0,0 @@ -# イントロダクション - -このマニュアルは、wolfHSM組込みハードウェアセキュリティモジュールライブラリの技術ガイドとして作成されています。wolfHSMの構築方法と使用開始方法を説明し、構築オプション、機能、移植性の向上、サポートなどの概要を示します。 - -このドキュメントのPDF版は [こちら](https://www.wolfssl.com/documentation/manuals/wolfhsm/wolfHSM-Manual.pdf) で入手できます。 - -## wolfHSMを選択する理由 - -車載HSM(Hardware Security Module)は、暗号鍵と処理のセキュリティを大幅に向上させます。これは、セキュリティの基盤である署名検証と暗号処理を物理的に独立したプロセッサに分離することで実現します。堅牢なセキュリティが求められるECUでは、推奨ではなく必須とされることがよくあります。よって、厳密なテストを行っている暗号化ライブラリwolfSSLを、Aurix Tricore TC3XX などの広く使用されている自動車用HSMでシームレスに動作するようにしました。wolfHSMが依存しているのはwolfCryptのみであり、ほぼすべての環境に移植できます。また、ユーザーフレンドリーなクライアント インターフェイスも提供しており、wolfCrypt APIを直接利用できます。 - -wolfHSMはECUのセキュリティとパフォーマンスを最大限に高めるべく、ハードウェア暗号化、不揮発性メモリ、各種隔離環境などと組み合わせて使用できるように設計しています。暗号エンジンwolfCryptをInfineon Aurix Tricore TC3XX などのハードウェアHSMに統合することで、SM2、SM3、SM4 などの中国政府義務アルゴリズムも利用できます。さらに、Kyber、LMS、XMSS などの耐量子暗号アルゴリズムを自動車ユーザーが簡単に利用できるようにし、顧客の要件に対応できるようにします。併せて、HSMでハードウェア暗号処理を利用できる場合は、これも利用してパフォーマンスを向上させます。 - -wolfBootは、ベアメタル環境のための安全かつポータブルなブートローダーソリューションです。最小限の設計と小さなHAL APIを活用した包括的なファームウェア認証および更新メカニズムを提供し、オペレーティングシステムやベアメタルアプリケーションから完全に独立しています。wolfBootは、フラッシュインターフェイスとプリブート環境を効率的に管理、アプリケーションを正確に測定および認証します。また、必要に応じてよりレイヤーの低いハードウェア暗号化も利用します。wolfBootはwolfHSM クライアントを使用し、HSM支援アプリケーションコアのセキュアブートを使用できます。さらに、wolfBootをHSMコア上で実行してHSMサーバーが損傷していないことを確認し、2次的な保護層を提供できます。この設定により、安全なブートシーケンスが保証されNVMサポートに依存するHSMコアのブートプロセスと適切に連携します。 diff --git a/wolfHSM/src-ja/chapter02.md b/wolfHSM/src-ja/chapter02.md deleted file mode 100644 index 6728c405..00000000 --- a/wolfHSM/src-ja/chapter02.md +++ /dev/null @@ -1,69 +0,0 @@ -# 概要 - -wolfHSMは、暗号操作・鍵管理・不揮発性ストレージの制御など、HSM操作用の統合APIを提供するソフトウェアフレームワークです。 -HSMアプリケーションに関連するコードの移植性を向上させるように設計しており、ベンダー固有のライブラリ呼び出しに縛られることなく、強力なセキュリティ機能を多くのハードウェア上で容易に使用できるようにします。 -wolfCrypt APIを直接使用できるため、クライアントアプリケーションが大幅に簡素化されます。ライブラリは、クライアントアプリで追加のロジックを必要とせずに、すべての機密性の高い暗号化操作をリモートプロシージャコールとしてHSMコアに自動的にオフロードします。 - -当初、主に自動車に搭載されるHSM対応マイクロコントローラを対象としていました。 -しかし現在では、自動車に限らずあらゆるユースケースにおいてPKCS11やAUTOSAR SHEなどの標準化されたインターフェイスとプロトコルをサポートできるようにしました。 -プラットフォームに将来追加される機能をサポートすることのできる、拡張可能なソリューションです。wolfCrypt以外の外部依存はなく、ほぼすべての実行環境に移植可能です。 - -## 機能 - -- ユーザーベースの権限による安全な不揮発性オブジェクトストレージ -- ハードウェアキーをサポートする暗号鍵管理 -- 互換性のあるデバイスに対するハードウェア暗号化サポート -- 完全に非同期のクライアントAPI -- 柔軟なコールバックアーキテクチャにより、ライブラリを変更せずにカスタムユースケースを実現 -- wolfCrypt APIをクライアントで直接使用し、HSMコアに自動的にオフロード -- 信頼チェーンをサポートするイメージマネージャー -- AUTOSARとの統合 -- SHE+との統合 -- PKCS11インターフェイスを使用可能 -- TPM 2.0インターフェイスを使用可能 -- Secure OnBoard Communication (SecOC) モジュール統合を使用可能 -- 証明書の処理 -- 共通鍵暗号・公開鍵暗号の両方に対応 -- 半導体ベンダーによって実装されたアルゴリズムだけでなく、wolfCryptに実装されているすべてのアルゴリズムを提供することで、「暗号アジリティ」をサポート -- FIPS 140-3認証を取得可能 - -## アーキテクチャ - - wolfHSMは、サーバーが信頼できる安全な環境(通常は安全なコプロセッサ上)で実行され、クライアントがライブラリであるクライアントサーバーモデルを採用しています。このアーキテクチャにより、機密性の高い暗号化操作と鍵管理がサーバー内で安全に処理され、クライアントライブラリがサーバーとのレイヤーの低い通信を抽象化します。 - -- サーバー: wolfHSMのサーバーコンポーネントは、HSMコアで実行されるスタンドアロンアプリケーションです。安全な環境内で暗号化操作、鍵管理、不揮発性ストレージを処理します。サーバーはクライアントからの要求を処理し、結果を返す役割を担います。 - -- クライアント: wolfHSMのクライアントコンポーネントは、ユーザーアプリケーションにリンクできるライブラリです。サーバーに要求を送信し、応答を受信するためのAPIを提供します。クライアントは、通信の複雑さを抽象化し、アプリケーションがHSMと安全かつ効率的に対話できるようにします。 - -## ポート - -wolfHSM自体には特定のハードウェアと対話するためのコードは含まれておらず、単体では実行できません。 wolfHSMをデバイスで実行するには、サーバ アプリケーションがクライアントと通信して実行できるように、必要なハードウェアドライバーと抽象化レイヤーを使用してライブラリを構成する必要があります。具体的には、次の要素が必要です。 - -- サーバーアプリケーションの起動とハードウェアの初期化 -- サーバーにおけるwolfCrypt構成 -- サーバーの不揮発性メモリ構成 -- サーバーとクライアントのトランスポート構成 -- サーバーとクライアントの接続処理 - -これらの要件を提供し、サーバーAPIを起動可能なアプリケーションにラップするコードを、wolfHSM「ポート」と呼んでいます。 - -wolfHSMの公式ポートは、サポートされているさまざまなアーキテクチャ用に提供しています。それぞれのポートには次のものが含まれます。 - -- スタンドアロンリファレンスサーバーアプリケーション: このアプリケーションは、HSMコアで実行され、すべての安全な操作を処理することを目的としています。すぐに使用できる状態で完全に機能しますが、エンドユーザーがカスタマイズして追加のユースケースをサポートすることもできます。 -- クライアントライブラリ: このライブラリは、ユーザーアプリケーションにリンクして、サーバーとの通信を容易にします。 - -### 対応状況 - -本章執筆時点において、次のデバイス/環境のポートをサポートしています。 - -- POSIX ランタイム -- ST Micro SPC58N\* -- Infineon Aurix TC3xx\* -- Infineon Aurix TC4xx\* (近日対応予定) -- Infineon Traveo T2G\* (近日対応予定) -- Renesas RH850\* (近日対応予定) -- NXP S32\* (近日対応予定) - -ここに示した環境のほか、いくつかの環境へのポートを現在準備中です。 - -\* 残念ながら、これらのポートでは、HSMコアに関する情報を取得するためにシリコンベンダーとのNDAが必要です。したがって、これらのプラットフォームのwolfHSMポートは一般には公開しておりません。ご興味がございましたら、info@wolfssl.jp までお問い合わせください。 diff --git a/wolfHSM/src-ja/chapter03.md b/wolfHSM/src-ja/chapter03.md deleted file mode 100644 index 04daad7b..00000000 --- a/wolfHSM/src-ja/chapter03.md +++ /dev/null @@ -1,201 +0,0 @@ -# wolfHSMの始め方 - -wolfHSMの最も一般的な使用例は、HSMコプロセッサを搭載したマルチコアデバイスのアプリケーションコアの1つで動作する既存のアプリケーションに、HSM対応の機能を追加することです。 - -デバイス上でwolfHSMを実行するために必要な最初のステップは、特定のwolfHSMポートの手順に従って、HSMコア上でリファレンスサーバーを実行することです。wolfHSMサーバーアプリケーションがデバイスにロードされて起動すると、クライアントアプリケーションはwolfHSMクライアントライブラリとリンクし、wolfHSMクライアント構造体のインスタンスを設定して、wolfHSMクライアントAPIとwolfCrypt APIを通じてHSMと対話できるようになります。 - -各wolfHSMポートには、デフォルトの通信チャネルの設定方法とサーバーとの対話方法を示すクライアントデモアプリが含まれています。また、サーバーのリファレンス実装は[サーバーコールバック](./chapter07.md)によってカスタマイズでき、その機能はクライアントリクエストを通じて呼び出すことができます。 - -## 基本的なクライアント設定 - -wolfHSMクライアントを使用するには、クライアントコンテキスト構造体を割り当て、有効なクライアントのパラメータを用いて初期化処理を実行する必要があります。 - -クライアントコンテキスト構造体`whClientContext`は、クライアントの内部状態とサーバーとの通信を保持します。すべてのクライアントAPIは、クライアントコンテキストへのポインタを受け取ります。 - -クライアント設定構造体には、サーバーとの通信用にコンテキストを設定・初期化するために使用される通信レイヤー設定(`whCommClientConfig`)が含まれています。`whCommClientConfig`構造体は、実際のトランスポート実装(組み込みまたはカスタム)をクライアントが使用する抽象的な通信インターフェースにバインドします。 - -クライアントを設定する一般的な手順は以下の通りです。 - -1. 目的のトランスポートのトランスポート設定構造体、コンテキスト、コールバック実装を割り当て、初期化 -2. 通信クライアント設定構造体を割り当て、手順1のトランスポート設定にバインド -3. 手順2の通信クライアント設定を使用してクライアント設定構造体を割り当て、初期化 -4. クライアントコンテキスト構造体を割り当て -5. `wh_Client_Init()`を呼び出してクライアント設定でクライアントを初期化 -6. クライアントAPIを使用してサーバーと接続 - -以下に、クライアントアプリケーション用の実装例を示します。 -ここでは、組み込みの共有メモリトランスポートレイヤを使用して、サーバーにエコーリクエストを送信します。 - -```c -#include /* for memcmp() */ -#include "wolfhsm/client.h" /* クライアントAPI(通信設定を含む) */ -#include "wolfhsm/wh_transport_mem.h" /* トランスポート実装 */ - -/* 手順1: 共有メモリトランスポート設定の割り当てと初期化 */ -/* 共有メモリトランスポート設定 */ -static whTransportMemConfig transportMemCfg = { /* 共有メモリ設定 */ }; -/* 共有メモリトランスポートコンテキスト(状態) */ -whTransportMemClientContext transportMemClientCtx = {0}; -/* 抽象的な通信トランスポートインターフェースを - 具体的な実装にバインドするコールバック構造体 */ -whTransportClientCb transportMemClientCb = {WH_TRANSPORT_MEM_CLIENT_CB}; - -/* 手順2: クライアント通信設定を割り当て、トランスポートにバインド */ -/* 選択したトランスポート設定を使用するようにクライアント通信を設定 */ -whCommClientConfig commClientCfg = { - .transport_cb = transportMemClientCb, - .transport_context = (void*)transportMemClientCtx, - .transport_config = (void*)transportMemCfg, - .client_id = 123, /* 一意のクライアント識別子 */ -}; - -/* 手順3: クライアント設定の割り当てと初期化 */ -whClientConfig clientCfg= { - .comm = commClientCfg, -}; - -/* 手順4: クライアントコンテキストの割り当て */ -whClientContext clientCtx = {0}; - -/* 手順5: 提供された設定でクライアントを初期化 */ -wh_Client_Init(&clientCtx, &clientCfg); - -/* 手順6: クライアントAPIを使用してサーバーと接続 */ - -/* 送受信データを保持するバッファ */ -char recvBuffer[WH_COMM_DATA_LEN] = {0}; -char sendBuffer[WH_COMM_DATA_LEN] = {0}; - -uint16_t sendLen = snprintf(&sendBuffer, - sizeof(sendBuffer), - "Hello World!\n"); -uint16_t recvLen = 0; - -/* エコーリクエストを送信し、応答を受信するまでブロック */ -wh_Client_Echo(client, sendLen, &sendBuffer, &recvLen, &recvBuffer); - -if ((recvLen != sendLen ) || - (0 != memcmp(sendBuffer, recvBuffer, sendLen))) { - /* エラー:送信したものと同じものがエコーバックされなかった */ -} -``` - -詳細については、[第5章:クライアントライブラリ](./chapter05.md)をご覧ください。 - -## 基本的なサーバ設定 - -*注:wolfHSMポートには、HSMコア上で実行するように設定済みのリファレンスサーバーアプリケーションが付属しているため、手動でのサーバー設定は必要ありません。* - -wolfHSMサーバーを使用するには、サーバーコンテキスト構造体を割り当て、有効なクライアントのパラメータを用いてを初期化処理を実行する必要があります。 -通常、クライアントとの通信、暗号化操作、鍵の管理、不揮発性オブジェクトの保存が含まれます。ただし、これらの設定コンポーネントをすべて初期化する必要はありません。必要なもののみ初期化します。 - -クライアント通信、NVMフラッシュ設定を使用したNVMオブジェクトストレージ、およびローカル暗号(ソフトウェアのみ)をサポートするサーバーを設定するために必要な手順を以下に示します。 - -1. サーバー通信設定の初期化 - 1\. 目的のトランスポートのトランスポート設定構造体、コンテキスト、コールバック実装を割り当て、初期化 - 2\. 手順1.1のトランスポート設定を使用して通信サーバー設定構造体を割り当て、初期化 -2. サーバーNVMコンテキストの初期化 - 1\. 低レベルフラッシュストレージドライバーの設定、コンテキスト、コールバック構造体を割り当て、初期化(これらの構造体の実装はポートによって提供されます) - 2\. NVMフラッシュ設定、コンテキスト、コールバック構造体を割り当て、初期化し、手順2.1のポートフラッシュ設定をそれらにバインド - 3\. NVMコンテキスト構造体を割り当て、`wh_Nvm_Init()`を使用して手順2.2の設定で初期化 -3. サーバー用の暗号コンテキスト構造体を割り当て、初期化 -4. wolfCryptを初期化(必ず、サーバーを初期化する前に行います) -5. サーバー設定構造体を割り当て、初期化し、通信サーバー設定、NVMコンテキスト、暗号コンテキストをバインド -6. サーバーコンテキスト構造体を割り当て、`wh_Server_Init()`を使用してサーバー設定で初期化 -7. 基盤となるトランスポートがクライアント通信に使用できる準備が整い次第、`wh_Server_SetConnected()`を使用してサーバー接続状態を接続済みに設定(詳細については[サンプルプログラム](https://github.com/wolfSSL/wolfHSM/tree/main/examples)を参照ください) -8. `wh_Server_HandleRequestMessage()`を使用してクライアントリクエストを処理 - -サーバーは、NVMフラッシュ設定を使用してNVMオブジェクトストレージをサポートするように設定できます。 -手順1の後に、サーバーで[NVMを初期化する](./chapter04.md#NVM-Architecture)手順を実行してください。 - -```c -#include /* for memcmp() */ -#include "wolfhsm/server.h" /* サーバーAPI(通信設定を含む) */ -#include "wolfhsm/wh_transport_mem.h" /* トランスポート実装 */ - -/* 手順1.1: 共有メモリトランスポート設定の割り当てと初期化 */ -/* 共有メモリトランスポート設定 */ -static whTransportMemConfig transportMemCfg = { /* 共有メモリ設定 */ }; - -/* 共有メモリトランスポートコンテキスト(状態) */ -whTransportMemServerContext transportMemServerCtx = {0}; - -/* 抽象的な通信トランスポートインターフェースを - 具体的な実装にバインドするコールバック構造体 */ -whTransportServerCb transportMemServerCb = {WH_TRANSPORT_MEM_SERVER_CB}; - -/* 手順1.2: 通信サーバー設定構造体を割り当て、 - トランスポートにバインド */ -/* 選択したトランスポート設定を使用するようにサーバー通信を設定 */ -whCommServerConfig commServerCfg = { - .transport_cb = transportMemServerCb, - .transport_context = (void*)transportMemServerCtx, - .transport_config = (void*)transportMemCfg, - .server_id = 456, /* 一意のサーバー識別子 */ -}; - -/* サーバーNVMコンテキストの初期化 */ - -/* 手順2.1: ポート固有のフラッシュストレージドライバー用の - コンテキストと設定の割り当てと初期化 */ - -/* ポートフラッシュコンテキスト(構造体名はポート固有) */ -MyPortFlashContext portFlashCtx = {0} - -/* ポートフラッシュ設定 */ -MyPortFlashConfig portFlashCfg = { /* ポート固有の設定 */ }; - -/* ポートフラッシュ用のNVMフラッシュコールバック実装 */ -whFlashCb portFlashCb = { /* NVMフラッシュコールバックのポートフラッシュ実装 */ }; - -/* 手順2.2: NVMフラッシュ設定構造体を割り当て、初期化し、 - 手順2.1のポート設定にバインド */ -whNvmFlashConfig nvmFlashCfg = { - .cb = portFlashCb, - .context = portFlashCtx, - .config = portFlashCfg, -}; -whNvmFlashContext nfc = {0}; - -/* 手順2.3: NVMコンテキスト、設定、コールバック構造体を割り当て、 - 手順2.2のNVMフラッシュ設定で初期化 */ -whNvmCb nvmFlashCb = {WH_NVM_FLASH_CB}; - -whNvmConfig nvmConf = { - .cb = nvmFlashCb; - .context = nfc; - .config = nvmFlashCfg, -}; -whNvmContext nvmCtx = {0}; - -wh_Nvm_Init(&nvmCtx, &whNvmConfig); - -/* 手順3: 暗号コンテキスト構造体の割り当てと初期化 */ -whServerCryptoContext cryptoCtx { - .devID = INVALID_DEVID; /* あるいは、カスタム暗号コールバックdevIDを設定 */ -}; - -/* サーバー設定の割り当てと初期化 */ -whServerConfig serverCfg = { - .comm = commServerCfg, - .nvm = nvmCtx, - .crypto = cryptoCtx, -}; - -/* 手順4: wolfCryptの初期化 */ -wolfCrypt_Init(); - -/* 手順5: サーバー設定構造体を割り当て、初期化し、 - 通信サーバー設定と暗号コンテキストをバインド */ -whServerContext server = {0}; -wh_Server_Init(&server, &serverCfg); - -/* トランスポートの準備が整い次第(例:共有メモリバッファがクリアされた後)、 - サーバー接続状態を接続済みに設定 */ -wh_Server_SetConnected(&server, WH_COMM_CONNECTED); - -/* クライアントリクエストの処理 */ -while (1) { - wh_Server_HandleRequestMessage(&server); -} -``` diff --git a/wolfHSM/src-ja/chapter04.md b/wolfHSM/src-ja/chapter04.md deleted file mode 100644 index de35be4d..00000000 --- a/wolfHSM/src-ja/chapter04.md +++ /dev/null @@ -1,285 +0,0 @@ -# ライブラリ構造 - -wolfHSMは、組込みシステム向けに安全で効率的なハードウェアセキュリティモジュール(HSM)APIを提供するために設計した、モジュラーで拡張可能なライブラリです。 -このライブラリは、特定のアプリケーションの要件を満たすために簡単に設定・組み合わせることが可能な一連の機能コンポーネントを中心に構築されています。 -この章では、コンポーネントアーキテクチャ、通信レイヤー、不揮発性メモリ(NVM)、鍵管理、暗号化操作、ハードウェアセキュリティモジュール(HSM)サポートなど、wolfHSMの主要な機能コンポーネントの概要を説明します。 - -## 目次 - -- コンポーネントアーキテクチャ -- 通信 - - 主要コンポーネント - - クライアント/サーバーAPI - - 通信レイヤー -- 不揮発性メモリ - - 不揮発性メモリのメタデータ - - 不揮発性メモリのアーキテクチャ - - 不揮発性メモリのバックエンド -- 鍵管理 -- 暗号処理 - - ハードウェア暗号サポート - -## コンポーネントアーキテクチャ - -wolfHSMの各コンポーネントは、共通の初期化、設定、コンテキストストレージアーキテクチャを持つように設計しています。 -これは、異なるハードウェアプラットフォームやビルド環境に簡単に移植できるようにするためです。 - -ハードウェアの詳細は、`void*`として参照される型付けされていないコンテキスト構造体にコールバック関数を関連付けることで、論理操作から抽象化しています。 - -### コンポーネントの初期化 - -wolfHSMコンポーネントの、一般的な設定と初期化の例を示します。 - -```c -#include "wolfhsm/component.h" /* wolfHSM コンポーネントの抽象APIリファレンス */ -#include "port/vendor/mycomponent.h" /* プラットフォーム固有の設定とコンテキスト構造体の定義、 - * およびコールバック関数の宣言 */ - -/* mycomponent用の関数コールバックのルックアップテーブルを提供。型は -wolfhsm/component.hで提供される抽象型であることに注意 */ -whComponentCb my_cb[1] = {MY_COMPONENT_CB}; - -/* 固定設定データ。関連データはinit()の実行中に構造体から -* コピーされることに注意 */ -const myComponentConfig my_config = { - .my_number = 3, - .my_string = "This is a string", -} - -/* myComponentの動的状態の静的割り当て */ -myComponentContext my_context[1] = {0}; - -/* プラットフォーム固有のコールバックを使用したコンポーネントの初期化 */ -const whComponentConfig comp_config[1] = { - .cb = my_cb, - .context = my_context, - .config = my_config - }; -whComponentContext comp_context[1] = {0}; -int rc = wh_Component_Init(comp_context, comp_config); - -rc = wh_Component_DoSomething(comp_context, 1, 2, 3); -rc = wh_Component_CleanUp(comp_context); -``` - -## 通信 - -wolfHSMの通信レイヤーは、クライアントとサーバー間において信頼性の高い双方向のパケットベースの通信を提供するように設計しています。 -このレイヤーは基盤となるトランスポートメカニズムを抽象化し、柔軟性とモジュール性を実現します。 -クライアントとサーバーの両方でリクエストとレスポンスの機能を分割していることで、メッセージ受信の同期的なポーリングや、割り込み/イベントサポートに基づく非同期処理を可能にしています。 - -### 主要コンポーネント - -- クライアント/サーバーAPI:クライアントとサーバー間の通信のためのメインインターフェース。これらはユーザーアプリケーションによって直接使用されるAPIです。 -- 通信レイヤー:クライアントとサーバー間で交換されるメッセージのフォーマットと構造を定義し、基盤となるトランスポートレイヤーの実装への抽象インターフェースを提供。 -- トランスポートレイヤー:基盤となるトランスポートの具体的な実装。クライアントとサーバー間でデータが実際にどのように転送されるかを定義します。 - -### クライアント/サーバーAPI - -高レベルのクライアントとサーバーAPI(`wolfhsm/wh_client.h`と`wolfhsm/wh_server.h`で定義)は、通信のための主要なインターフェースです。 -これらの関数は、呼び出し元から低レベルの通信の詳細を抽象化し、論理操作のためのシンプルな分割トランザクションインターフェースを提供します。 - -以下に、クライアントAPIを使用してサーバーにエコーリクエストを送信する場合の実装例を示します。 - -```c -/* エコーリクエストを送信 */ -wh_Client_EchoRequest(&clientCtx, sendLen, &sendBuffer); - -/* 任意で他の処理を実行 */ - -/* サーバーのレスポンスをポーリング */ -while (WH_ERROR_NOTREADY == wh_Client_EchoResponse(client, &recv_len, recv_buffer)); -``` - -### 通信レイヤー - -通信レイヤーは、より高レベルのクライアントとサーバーのAPIによって呼び出され、下位レベルのトランスポートとの間でデータを送受信するためのメッセージング構造と制御ロジックをカプセル化します。 -下位レベルのトランスポートと対話するための抽象インターフェース関数を提供する通信クライアントと通信サーバーの抽象化を実現しています。 -通信レイヤーAPIは、リクエストとレスポンスの送受信機能で構成されており、これらのリクエストとレスポンスは高レベルの操作ではなくメッセージに関連します。 - -各クライアントは、一度に1つのリクエストのみをサーバーに送信できます。 -サーバーはクライアントの分離を確実にするため、一度に1つのリクエストを処理します。 - -#### メッセージ - -メッセージは、可変長のペイロードを持つヘッダーで構成されます。 -ヘッダーはシーケンスIDとリクエストまたはレスポンスの種類を示します。併せて、補助フラグやセッション情報を提供するための追加フィールドも提供します。 - -```c -/* wolfhsm/wh_comm.h */ - -typedef struct { - uint16_t magic; - uint16_t kind; - uint16_t seq; - uint16_t size; -} whCommHeader; -``` - -メッセージは、サーバーが望ましい機能を実行するために必要なリクエストデータと、機能の実行結果をクライアントに返すためのレスポンスをカプセル化するために使用されます。 -メッセージタイプは、機能を実行するコンポーネントに基づいてグループ化され、列挙された機能のどれが実行されているかを一意に識別します。 -互換性(エンディアンとバージョン)を確保するためにメッセージにはMagicフィールドが含まれており、ペイロード内で渡されるデータをネイティブ処理用にデマーシャリングするために必要な操作を示す既知の値が使用されます。 -各機能コンポーネントには、ネイティブ値と「on-the-wire」メッセージフォーマット間の変換を行うリモート実装があります。 -サーバーは、レスポンスフォーマットがリクエストフォーマットと一致することを保証します。 - -メッセージ内でデータコンテンツを渡すことに加えて、特定のメッセージタイプは共有またはマップされたメモリポインタの受け渡しもサポートしています。 -これは、特にサーバーコンポーネントがDMA方式でデータに直接アクセスできる可能性のある、パフォーマンスクリティカルな操作のためのものです。 -整数ポインタサイズ(IPS)と`size_t`の違いを避けるため、可能な場合はすべてのポインタとサイズを`uint64_t`として送信する必要があります。 - -メッセージは、ヘッダーのMagicフィールドを使用して「on-the-wire」フォーマットでエンコードされ、構造体メンバーの指定されたエンディアンと通信ヘッダーのバージョン(現在は0x01)が示されます。 -リクエストメッセージを処理するサーバーコンポーネントは、提供された値をネイティブフォーマットに変換し、タスクを実行し、結果をリクエストのフォーマットに再エンコードします。 -クライアントでは、リクエストフォーマットと一致しないメッセージを処理する必要はありません。 -エンコードされたメッセージは、Magicフィールドで指定されたエンディアンで、かつネイティブ構造体と同じサイズとレイアウトを想定しています。 - -以下に、クライアント通信レイヤーがリクエストを送信する際の実装例を示します。 - -```c -uint16_t req_magic = wh_COMM_MAGIC_NATIVE; -uint16_t req_type = 123; -uint16_t request_id; -char* req_data = "RequestData"; -rc = wh_CommClient_SendRequest(context, req_magic, req_type, &request_id, - sizeof(req_data), req_data); -/* 他のタスクを実行 */ - -uint16_t resp_magic, resp_type, resp_id, resp_size; -char response_data[20]; -while((rc = wh_CommClient_RecvResponse(context,&resp_magic, &resp_type, &resp_id, - &resp_size, resp_data)) == WH_ERROR_NOTREADY) { - /* 他のタスクを実行 or yield */ -} -``` - -メッセージレイヤーに渡されるトランスポートエラーは致命的であると想定されます。 -クライアント/サーバーはコンテキストをクリーンアップする必要があることに注意してください。 - -### トランスポート - -トランスポートは、ライブラリがリクエストまたはレスポンスとして処理するために、可変サイズ(最大MTUまで)の完全なパケット(バイト列)をメッセージレイヤーに提供します。 -`whTransportClientCb`で定義された抽象インターフェースを実装し、データの送受信が必要な時にcommClient/commServerによって直接呼び出されます。 - -`whTransportClientCb`インターフェースを実装するカスタムトランスポートモジュールは、サーバーとクライアントに登録できます。 -その後、標準的なサーバーとクライアントのリクエスト/レスポンス機能を介して自動的に使用されます。 - -メモリバッファトランスポートモジュールとPOSIX TCPソケットトランスポートの実装例は、wolfHSMでサポートしているトランスポートの中で見ることができます。 - -#### サポートしているトランスポート - -wolfHSMは、以下2つの組み込みトランスポートを付属しています。 - -- メモリバッファトランスポート(`wh_transport_mem.c`) -- POSIX TCPソケットトランスポート(`port/posix_transport_tcp.c`) - -メモリトランスポートは、ほとんどの組込みwolfHSMポートのデフォルトトランスポートであり、wolfHSMコアライブラリの一部です。 -クライアントとサーバー間の共有メモリブロックを使用して、トランスポートコールバックの具体的な実装を提供します。 -共有メモリトランスポートメカニズムは、2つのメモリブロックを割り当てることで動作します。 -1つは受信リクエスト用、もう1つは送信レスポンス用です。クライアントは受信メモリブロックにリクエストを書き込み、送信メモリブロックからレスポンスを読み取ります。 -サーバーは受信メモリブロックからリクエストを読み取り、送信メモリブロックにレスポンスを書き込みます。 -各ブロックには、使用準備が整ったときに消費者に通知する制御とステータスフラグが含まれています。 -このメカニズムは、システムコールやネットワーク通信の必要性を回避するため、高速かつ効率的になるように設計されています。 - -POSIX TCPトランスポートは、wolfHSM POSIXポートの一部です。 -クライアントとサーバー間のデータのトランスポート媒体としてTCPソケットを使用します。 -ソケットはIPv4のみで、ノンブロッキングです。 - -## 不揮発性メモリ - -wolfHSMにおける不揮発性メモリ(NVM)は、メタデータとデータブロックを持つ永続的なオブジェクトを管理するために使用されます。 -NVMライブラリは、成功を返す前にトランザクションが完全にコミットされることを保証する、信頼性の高い原子的な操作を確保します。 -主要な操作には、オブジェクトの追加、一覧表示、読み取り、破棄、および関連するメタデータの取得が含まれます。 - -NVMの主要な機能として、以下が含まれます。 - -- アクセス可能なNVM内の可変サイズデータとメタデータ(ID、ラベル、長さ、アクセス、フラグ)を関連付けるためのAPI -- ステータスフラグを持つ2つの消去可能なパーティションを使用して、常に復元可能 -- オブジェクトは次のエントリを使用して追加され、空き領域にプログラムされる -- 重複したIDは許可されるが、最新のものだけが読み取り可能 -- オブジェクトは、リストされたオブジェクトを除いて、非アクティブなパーティションに全領域をコピーすることで破棄される -- 復旧時に後のオブジェクトを識別するため、内部エポックカウンタを使用 - -### 不揮発性メモリのメタデータ - -不揮発性メモリ(NVM)メタデータは、NVMに保存されたオブジェクトを管理および記述するために使用されます。 -このメタデータは、識別子、アクセス権限、フラグ、その他の属性など、各オブジェクトに関する重要な情報を提供します。 -メタデータにより、NVM内のオブジェクトを確実に管理、アクセス、操作することができます。 - -```c -/* NVMオブジェクトのユーザー指定メタデータ */ -typedef struct { -whNvmId id; / 一意の識別子 / -whNvmAccess access; / アクセス権限 / -whNvmFlags flags; / 追加フラグ / -whNvmSize len; / データの長さ(バイト単位) / -uint8_t label[WOLFHSM_NVM_LABEL_LEN]; / ラベル */ -} whNvmMetadata; -``` - -- ID (`whNvmId id`):NVMオブジェクトの一意の識別子です。このIDはNVM内の特定のオブジェクトを参照しアクセスするために使用されます。オブジェクトの読み取り、書き込み、削除などの操作を可能にします。 -- アクセス (`whNvmAccess access`):オブジェクトのアクセス権限を定義します。このフィールドは、誰がどのような条件でオブジェクトにアクセスできるかを指定します。セキュリティポリシーを実施し、権限のあるエンティティのみがオブジェクトと対話できることを保証します。 -- フラグ (`whNvmFlags flags`):追加情報を提供したりオブジェクトの動作を変更したりする追加フラグです。フラグは、オブジェクトが読み取り専用か、一時的か、その他の特定のプロパティを持つかなど、特別な属性や状態でオブジェクトをマークするために使用できます。 -- 長さ (`whNvmSize len`):オブジェクトに関連付けられたデータの長さ(バイト単位)です。 -- ラベル (`uint8_t label[]`):オブジェクトの人間が読める形式のラベルまたは名前です。 - -### 不揮発性メモリのアーキテクチャ - -wolfHSMサーバーは、不揮発性メモリ(NVM)操作を処理するために汎用コンポーネントアーキテクチャアプローチに従います。 -設定は汎用部分と特定部分に分かれており、柔軟性とカスタマイズ性を提供します。 - -1. **汎用設定 (wh_nvm.h):** このヘッダーファイルは、NVM操作の汎用インターフェースを定義します。`nvm_Read`、`nvm_Write`、`nvm_Erase`、`nvm_Init`などのNVM操作用の関数ポインタが含まれています。これらの関数ポインタは`whNvmConfig`構造体の一部であり、実際のNVM実装を抽象NVMインターフェースにバインドするために使用されます。 - -2. **特定設定 (wh_nvm_flash.c, wh_nvm_flash.h):** これらのファイルは、フラッシュメモリ用のNVMインターフェースの具体的な実装を提供します。ここで定義される関数は、汎用インターフェースで定義された関数シグネチャに準拠しており、NVM操作の実際の実装として使用できます。 - -`whServerContext`構造体には`whNvmConfig`メンバーが含まれています。これはNVM操作をサーバーコンテキストにバインドするために使用され、サーバーが設定されたNVMインターフェースを使用してNVM操作を実行できるようにします。 - -サーバーでNVMを初期化するには、以下の手順が必要です。 - -1. `whNvmConfig`構造体を割り当て、初期化し、特定のNVMバックエンド(例:`wh_nvm_flash.c`から)へのバインディングを提供 -2. `whServerConfig`構造体を割り当て、初期化し、その`nvmConfig`メンバーを手順1で初期化した`whNvmConfig`構造体に設定 -3. `whServerContext`構造体を割り当て -4. `wh_Server_Init()`を呼び出して、`whServerConfig`構造体でサーバーを初期化 - -これにより、サーバーは指定されたバッキングストアで設定されたNVM操作を使用できるようになり、`whNvmConfig`構造体で異なる実装を提供することで簡単に入れ替えることができます。 - -### 不揮発性メモリのバックエンド - -現在、wolfHSMがサポートしているNVMバックエンドプロバイダーは、NVMフラッシュモジュール(`wh_nvm_flash.c`)のみです。 -このモジュールは、NVMインターフェース関数(`wh_nvm.h`)の具体的な実装を提供し、NVMデータストアをフラッシュメモリデバイスにマッピングします。 -低レベルのフラッシュドライバーはデバイス固有であり、それ自体が汎用コンポーネント(`wh_flash.h`)として指定され、ターゲットハードウェアに応じて入れ替えることができます。 - -## 鍵管理 - -wolfHSMライブラリは、不揮発性メモリからの鍵の保存、読み込み、エクスポート、高速アクセスのためにRAMに頻繁に使用される鍵のキャッシング、およびハードウェア専用デバイス鍵との対話など、包括的な鍵管理機能を提供します。 -鍵は、対応するアクセス保護とともに、他のNVMオブジェクトと並んで不揮発性メモリに保存されます。 -wolfHSMは、特定のコンシューマーが使用するために鍵が選択されたとき、必要な暗号化ハードウェアに鍵を自動的に読み込みます。 -鍵管理APIの詳細については、[クライアントライブラリ](./chapter05.md)と[APIドキュメント](./appendix01.md)のセクションをご参照ください。 - -## 暗号処理 - -wolfHSMの特徴的な機能の1つは、クライアントアプリケーションがwolfCrypt APIを直接使用できるようにしながら、基盤となる暗号化操作を実際にHSMコア上で実行することです。 -これは以下のメリットをもたらします。 - -- クライアントアプリケーションは、HSM間でデータを双方向に受け渡すために必要な複雑な通信トランザクションを設定する必要がありません。これにより、劇的にシンプルになります。 -- wolfCrypt呼び出しのパラメータを1つ変更するだけで、ローカルとリモートのHSM実装を簡単に切り替えることができます。実装の最大限の柔軟性と開発の容易さを実現します。クライアントアプリケーションの開発は、HSMコアがオンラインになる前でも、wolfCryptのローカルインスタンスでプロトタイプを作成できます。 -- wolfHSM APIは、シンプルかつ安定していて、豊富なドキュメントがあり、あらゆる環境でその動作が検証されています。 - -wolfCrypt API呼び出しをwolfHSMサーバーに簡単にリダイレクトできる機能は、wolfCryptの「暗号コールバック」(cryptocbとも呼ばれる)に基づいています。 - -wolfHSMクライアントは、[暗号コールバック](https://www.wolfssl.com/documentation/manuals/wolfssl/chapter06.html#crypto-callbacks-cryptocb)としてリモートプロシージャコール(RPC)ロジックを実装することで、wolfCrypt API呼び出しをwolfHSMサーバーにリダイレクトできます。 -wolfCryptの暗号コールバックフレームワークにより、ユーザーは選択した暗号化アルゴリズムのデフォルト実装を上書きし、実行時に独自のカスタム実装を提供できます。 -wolfHSMクライアントライブラリは、wolfCryptに暗号コールバックを登録し、各wolfCrypt暗号化API関数を安全な環境で実行されるHSMサーバーへのリモートプロシージャコールに変換します。 -暗号コールバックは、ほとんどのwolfCrypt API呼び出しで受け入れられるデバイスID(`devId`)パラメータに基づいて選択されます。 - -wolfHSMは、wolfHSMサーバー暗号化デバイスを表す`WOLFHSM_DEV_ID`値を定義しており、これを任意のwolfCrypt関数の`devId`パラメータとして渡すことができます。 -`devId`パラメータをサポートするwolfCrypt APIには`WOLFHSM_DEV_ID`を渡すことができます。 -これがサポートされている場合、暗号化操作は自動的にwolfHSMサーバーによって実行されます。 - -### ハードウェア暗号サポート - -多くのHSMデバイスは、いくつかのアルゴリズムをターゲットとしたハードウェアアクセラレーション機能も備えています。 -wolfHSMサーバーは、HSMサーバーサイドの暗号化処理をデバイスハードウェアにオフロードすることもサポートしています。 -HSMデバイスが対応している場合、wolfHSMサーバーはユーザーからの特別な入力を必要とせずに、これを自動的に行うように設定できます。 -デバイス固有のハードウェアアクセラレーション機能については、そのデバイスのwolfHSMポートのドキュメントをご覧ください。 - -## AUTOSAR SHE - -(本章は後日提供予定です。) diff --git a/wolfHSM/src-ja/chapter05.md b/wolfHSM/src-ja/chapter05.md deleted file mode 100644 index b5f4477d..00000000 --- a/wolfHSM/src-ja/chapter05.md +++ /dev/null @@ -1,396 +0,0 @@ -# クライアントライブラリ - -クライアントライブラリAPIは、ユーザーがwolfHSMと対話するための主要な手段です。 -利用可能な関数の完全なリストとその説明については、[APIドキュメント](appendix01.md)をご参照ください。 - -## APIの返り値 - -すべてのクライアントAPI関数は、成功または失敗の種類を示すwolfHSMエラーコードを返します。 -一部の失敗は重大なエラーですが、他の失敗は単にユーザーからのアクションが必要であることを示すものもあります(例:ノンブロッキング操作の場合の`WH_ERROR_NOTREADY`)。 -多くのクライアントAPIは、サーバーエラーコード(場合によっては追加のステータス)もユーザーに伝達します。 -これにより、基礎となるリクエストトランザクションは成功したものの、サーバーが操作を実行できなかった場合にも対応できます。 -例えば、存在しないNVMオブジェクトをサーバーに要求した場合、NVMが満杯時にオブジェクトを追加しようとした場合、またはサーバーが対応するように設定されていない暗号化アルゴリズムを使用しようとした場合などが該当します。 - -エラーコードは`wolfhsm/wh_error.h`で定義しています。詳細については、APIドキュメントをご参照ください。 - -## 分割トランザクション処理 - -ほとんどのクライアントAPIは完全に非同期で、分割トランザクションに分解されています。 -つまり、操作リクエストとレスポンスについて別々の関数があります。 -リクエスト関数はサーバーにリクエストを送信し、ブロックせずに即座に戻ります。 -レスポンス関数は基礎となるトランスポートをポーリングしてレスポンスを確認し、レスポンスが存在する場合は処理を行い、まだ到着していない場合は即座に戻ります。 -これにより、クライアントのCPUサイクルを無駄にすることなく、サーバーに長時間実行される操作をリクエストできます。 -以下に、「echo」メッセージを使用した非同期リクエストとレスポンスの呼び出し例を示します。 - -```c -int rc; - -/* echoリクエストを送信 */ -rc = wh_Client_EchoRequest(&clientCtx, sendLen, &sendBuffer); -if (rc != WH_ERROR_OK) { - /* エラー処理 */ -} - -/* 他の処理を実行... */ - -/* サーバーレスポンスをポーリング */ -while ((rc = wh_Client_EchoResponse(client, &recv_len, recv_buffer)) == WH_ERROR_NOTREADY) { - /* 他の処理を実行するか、または制御を譲る */ -} - -if (rc != WH_ERROR_OK) { - /* エラー処理 */ -} -``` - -## クライアントコンテキスト - -クライアントコンテキスト構造体(`whClientContext`)は、クライアントの実行時状態を保持し、サーバーとの接続のエンドポイントを表します。 -また、クライアントとサーバーのコンテキストは1対1の関係にあります。つまり複数のサーバーと対話するアプリケーションでは、サーバーごとに1つのクライアントコンテキストが必要になります。 -各クライアントAPI関数は、クライアントコンテキストを引数として受け取り、どのサーバー接続に対応する操作かを示します。 -wolfSSLに慣れている方であれば、`WOLFSSL`接続コンテキスト構造体と同様の使い方をするとご認識いただいてよいかもしれません。 - -### クライアントコンテキストの初期化 - -クライアントコンテキストで任意のクライアントAPIを使用する前に、`whClientConfig`設定構造体と`wh_Client_Init()`関数を使用して構造体を設定し、初期化する必要があります。 - -クライアント設定構造体は、サーバー通信のためのコンテキストを設定・初期化するために使用される通信層設定(`whCommClientConfig`)を保持します。 -`whCommClientConfig`構造体は、実際のトランスポート実装(組み込みまたはカスタム)を、クライアントが使用する抽象的な通信インターフェースにバインドします。 - -クライアントを設定する一般的な手順は以下の通りです。 - -1. 目的のトランスポートのためのトランスポート設定構造体、コンテキスト、およびコールバック実装を割り当てて初期化する -2. 通信クライアント設定構造体を割り当て、クライアントが使用できるようにステップ1のトランスポート設定にバインドする -3. ステップ2の通信クライアント設定を使用してクライアント設定構造体を割り当てて初期化する -4. クライアントコンテキスト構造体を割り当てる -5. `wh_Client_Init()`を呼び出してクライアント設定でクライアントを初期化する -6. クライアントAPIを使用してサーバーと接続する - -以下に、組み込みの共有メモリトランスポートを使用するクライアントアプリケーションの設定例を示します。 - -```c -#include /* for memcmp() */ -#include "wolfhsm/client.h" /* クライアントAPI(通信設定を含む) */ -#include "wolfhsm/wh_transport_mem.h" /* トランスポート実装 */ - -/* ステップ1: 共有メモリトランスポート設定の割り当てと初期化 */ -/* 共有メモリトランスポート設定 */ -static whTransportMemConfig transportMemCfg = { /* 共有メモリ設定 */ }; -/* 共有メモリトランスポートコンテキスト(状態) */ -whTransportMemClientContext transportMemClientCtx = {0}; -/* 抽象的な通信トランスポートインターフェースを - * 具体的な実装にバインドするコールバック構造体 */ -whTransportClientCb transportMemClientCb = {WH_TRANSPORT_MEM_CLIENT_CB}; - -/* ステップ2: クライアント通信設定の割り当てとトランスポートへのバインド */ -/* 選択したトランスポート設定を使用するようにクライアント通信を設定 */ -whCommClientConfig commClientCfg[1] = {{ - .transport_cb = transportMemClientCb, - .transport_context = (void*)transportMemClientCtx, - .transport_config = (void*)transportMemCfg, - .client_id = 123, /* 一意のクライアント識別子 */ -}}; - -/* ステップ3: クライアント設定の割り当てと初期化 */ -whClientConfig clientCfg= { - .comm = commClientCfg, -}; - -/* ステップ4: クライアントコンテキストの割り当て */ -whClientContext clientCtx = {0}; - -/* ステップ5: 提供された設定でクライアントを初期化 */ -wh_Client_Init(&clientCtx, &clientCfg); -``` - -これでクライアントコンテキストが初期化され、作業を実行するためにクライアントライブラリAPI関数で使用できるようになりました。 -引き続き、サーバーにechoリクエストを送信してみます。 - -```c -/* ステップ6: クライアントAPIを使用してサーバーと対話 */ - -/* 送受信データを保持するバッファ */ -char recvBuffer[WH_COMM_DATA_LEN] = {0}; -char sendBuffer[WH_COMM_DATA_LEN] = {0}; - -uint16_t sendLen = snprintf(&sendBuffer, - sizeof(sendBuffer), - "Hello World!\n"); -uint16_t recvLen = 0; - -/* echoリクエストを送信し、レスポンスを受信するまでブロック */ -wh_Client_Echo(client, sendLen, &sendBuffer, &recvLen, &recvBuffer); - -if ((recvLen != sendLen ) || - (0 != memcmp(sendBuffer, recvBuffer, sendLen))) { - /* エラー:送信したものと同じものが返ってこなかった */ -} -``` - -設定と構造体の組み合わせが少々複雑だと感じるかもしれません。 -しかし、これによりクライアントコードを変更することなく、異なるトランスポート実装に簡単に入れ替えられるようにしています。 -例えば、共有メモリトランスポートからTCPトランスポートに切り替える場合、トランスポート設定とコールバック構造体を変更するだけで済み、クライアントコードの残りの部分(上記の手順2以降のすべて)は同じままです。 - -```c -#include /* for memcmp() */ -#include "wolfhsm/client.h" /* クライアントAPI(通信設定を含む) */ -#include "port/posix_transport_tcp.h" /* トランスポート実装 */ - -/* ステップ1: POSIX TCPトランスポート設定の割り当てと初期化 */ -/* クライアント設定/コンテキスト */ -whTransportClientCb posixTransportTcpCb = {PTT_CLIENT_CB}; -posixTransportTcpClientContext posixTranportTcpCtx = {0}; -posixTransportTcpConfig posixTransportTcpCfg = { - /* IPとポートの設定 */ -}; - -/* ステップ2: クライアント通信設定の割り当てとトランスポートへのバインド */ -/* 選択したトランスポート設定を使用するようにクライアント通信を設定 */ -whCommClientConfig commClientCfg = {{ - .transport_cb = posixTransportTcpCb, - .transport_context = (void*)posixTransportTcpCtx, - .transport_config = (void*)posixTransportTcpCfg, - .client_id = 123, /* 一意のクライアント識別子 */ -}}; - -/* 以降のステップは同じ... */ -``` - -ステップ6のechoリクエストはあくまでも単純な使用例です。 -サーバーとの接続が設定されれば、任意のクライアントAPIを使用できます。 - -## 不揮発性メモリ操作 - -このセクションでは、クライアントNVM APIの使用方法の例を示します。 -分割トランザクションAPIも同様に使用できますが、簡単のためにブロッキングAPIを使用します。 - -クライアントがサーバーのNVMストレージを使用するには、まず初期化リクエストをサーバーに送信します。 -現時点では、これによってサーバー側で何らかのアクションが実行されることはありません。 -しかし将来的にはここに実装を加える可能性があるため、クライアントアプリケーションに初期化リクエストを含めることを推奨します。 - -```c -int rc; -int serverRc; -uint32_t clientId; /* 現時点では未使用 */ -uint32_t serverId; - -rc = wh_Client_NvmInit(&clientCtx, &serverRc, &clientId, &serverId); - -/* ローカルとリモートの両方のエラーコードをチェック */ -/* serverIdにはサーバーの一意のIDが格納される */ -``` - -初期化が完了すると、クライアントは`NvmAddObject`関数を使用してオブジェクトを作成し追加できます。 -すべてのオブジェクトに対してメタデータエントリを作成する必要があることに注意してください。 - -```c -int serverRc; - -whNvmId id = 123; -whNvmAccess access = WOLFHSM_NVM_ACCESS_ANY; -whNvmFlags flags = WOLFHSM_NVM_FLAGS_ANY; -uint8_t label[] = “My Label”; - -uint8_t myData[] = “This is my data.” - -whClient_NvmAddObject(&clientCtx, id, access, flags, strlen(label), &label, sizeof(myData), &myData, &serverRc); -``` - -既存のオブジェクトに対応するデータは、その場で更新できます。 - -```c -byte myUpdate[] = “This is my update.” - -whClient_NvmAddObject(&clientCtx, &myMeta, sizeof(myUpdate), myUpdate); -``` - -トランスポート経由でコピーして送信すべきでないオブジェクトについては、`NvmAddObject`関数のDMAバージョンを使用できます。 -これらは値ではなく参照によってデータをサーバーに渡すため、サーバーが直接メモリ内のデータにアクセスできます。 -ただし、サーバーがクライアントのアドレスにアクセスする前に、プラットフォームがカスタムのアドレス変換またはキャッシュ無効化を必要とする場合は、[DMAコールバック](./chapter07#DMA-Callbacks)を実装する必要があることにご注意ください。 - -```c -whNvmMetadata myMeta = { - .id = 123, - .access = WOLFHSM_NVM_ACCESS_ANY, - .flags = WOLFHSM_NVM_FLAGS_ANY, - .label = “My Label” -}; - - -uint8_t myData[] = “This is my data.” - -wh_Client_NvmAddObjectDma(client, &myMeta, sizeof(myData), &myData), &serverRc); -``` - -NVMオブジェクトのデータは`NvmRead`関数を使用して読み取ることができます。 -また、`AddObjectDma`に対応する`NvmRead`関数のDMAバージョンも存在し、同様に使用できます。 - -```c -const whNvmId myId = 123; /* 読み取りたいオブジェクトのID */ -const whNvmSize offset = 0; /* オブジェクトデータへのバイトオフセット */ - -whNvmSize outLen; /* リクエストされたデータのバイト長が格納される */ -int outRc; /* サーバーのリターンコードが格納される */ - -byte myBuffer[BIG_SIZE]; - -whClient_NvmRead(&clientCtx, myId, offset, sizeof(myData), &serverRc, outLen, &myBuffer) -/* または DMA経由で */ -whClient_NvmReadDma(&clientCtx, myid, offset, sizeof(myData), &myBuffer, &serverRc); -``` - -オブジェクトは`NvmDestroy`関数を使用して削除/破棄できます。 -これらの関数は、削除するオブジェクトIDのリスト(配列)を引数に取ります。 -リスト内のIDがNVMに存在しない場合でもエラーは発生しません。 - -```c -whNvmId idList[] = {123, 456}; -whNvmSize count = sizeof(myIds)/ sizeof(myIds[0]); -int serverRc; - -wh_Client_NvmDestroyObjectsRequest(&clientCtx, count, &idList); -wh_Client_NvmDestroyObjectsResponse(&clientCtx, &serverRc); -``` - -NVM内のオブジェクトは、`NvmList`関数を使用して列挙できます。 -この関数は、`start_id`から始まるNVMリスト内の次にマッチするIDを取得し、`access`と`flags`にマッチするIDの総数を`out_count`に設定します。 - -```c -int wh_Client_NvmList(whClientContext* c, - whNvmAccess access, whNvmFlags flags, whNvmId start_id, - int32_t *out_rc, whNvmId *out_count, whNvmId *out_id); -``` - -すべてのNVM API関数の詳細な説明については、[APIドキュメント](./appendix01.md)をご参照ください。 - -## 鍵管理 - -wolfCryptで使用することを意図した鍵は、以下のAPIを使用してHSMのキーストアにロードし、必要に応じてNVMに保存できます。 - -```c -#include "wolfhsm/wh_client.h" - -uint16_t keyId = WOLFHSM_KEYID_ERASED; -uint32_t keyLen; -byte key[AES_128_KEY_SIZE] = { /* AES鍵 */ }; -byte label[WOLFHSM_NVM_LABEL_LEN] = { /* 鍵ラベル */ }; - -whClientContext clientCtx; -whClientCfg clientCfg = { /* 設定 */ }; - -wh_Client_Init(&clientCtx, &clientCfg); - -wh_Client_KeyCache(clientCtx, 0, label, sizeof(label), key, sizeof(key), &keyId); -wh_Client_KeyCommit(clientCtx, keyId); -wh_Client_KeyEvict(clientCtx, keyId); -keyLen = sizeof(key); -wh_Client_KeyExport(clientCtx, keyId, label, sizeof(label), key, &keyLen); -wh_Client_KeyErase(clientCtx, keyId); -``` - -`wh_Client_KeyCache`は、鍵とラベルをHSMのRAMキャッシュに格納し、渡された`keyId`と関連付けます。 -`WOLFHSM_KEYID_ERASED`を`keyId`として使用すると、wolfHSMは新しい一意の`keyId`を割り当て、keyIdパラメータを通じて返します。 -wolfHSMのキャッシュスロットの数は`WOLFHSM_NUM_RAMKEYS`で設定された数に制限されており、すべての鍵スロットが満杯の場合は`WH_ERROR_NOSPACE`を返します。 -キャッシュとNVMの両方に存在する鍵は、NVMにバックアップされているため、より多くの鍵のためのスペースを確保するためにキャッシュから削除されます。 - -`wh_Client_KeyCommit`は、キャッシュされた鍵をkeyIdで指定されたキーとしてNVMに保存します。 - -`wh_Client_KeyEvict`は、鍵をキャッシュから削除しますが、コミットされている場合はNVMには残します。 - -`wh_Client_KeyExport`は、鍵の内容をHSMからクライアントに読み出します。 - -`wh_Client_KeyErase`は、指定された鍵をキャッシュから削除し、NVMからも消去します。 - -## 暗号操作 - -クライアントアプリケーションでwolfCryptを使用する場合、`devId`引数として`WOLFHSM_DEV_ID`を渡すことで、互換性のある暗号化操作をwolfHSMサーバーで実行できます。 -ただし、wolfHSMのリモート暗号化を使用する前に、wolfHSMクライアントを初期化する必要があります。 - -wolfHSMがそのアルゴリズムをまだサポートしていない場合、API呼び出しは`CRYPTOCB_UNAVAILABLE`を返します。 - -以下に、クライアントアプリケーションがwolfHSMサーバーで`AES CBC`暗号化操作を実行する例を示します。 - -```c -#include "wolfhsm/client.h" -#include "wolfssl/wolfcrypt/aes.h" - -whClientContext clientCtx; -whClientCfg clientCfg = { /* 設定 */ }; - -wh_Client_Init(&clientCtx, &clientCfg); - -Aes aes; -byte key[AES_128_KEY_SIZE] = { /* AES鍵 */ }; -byte iv[AES_BLOCK_SIZE] = { /* AES IV */ }; - -byte plainText[AES_BLOCK_SIZE] = { /* 平文 */ }; -byte cipherText[AES_BLOCK_SIZE]; - -wc_AesInit(&aes, NULL, WOLFHSM_DEV_ID); - -wc_AesSetKey(&aes, &key, AES_BLOCK_SIZE, &iv, AES_ENCRYPTION); - -wc_AesCbcEncrypt(&aes, &cipherText, &plainText, sizeof(plainText)); - -wc_AesFree(&aes); -``` - -クライアント所有の鍵の代わりにHSM所有の鍵(例:HSMハードウェアキー)を使用する必要がある場合、 -`wh_Client_SetKeyAes`(または他の暗号化アルゴリズム用の同様の関数)などのクライアントAPI関数を使用します。 -これにより、指定されたHSMキーを後続の暗号化操作に使用するようwolfHSMに指示できます。 - -```c -#include "wolfhsm/client.h" -#include "wolfssl/wolfcrypt/aes.h" - -whClientContext clientCtx; -whClientCfg clientCfg = { /* 設定 */ }; - -wh_Client_Init(&clientCtx, &clientCfg); - -uint16_t keyId; -Aes aes; -byte key[AES_128_KEY_SIZE] = { /* AES鍵 */ }; -byte label[WOLFHSM_NVM_LABEL_LEN] = { /* 鍵ラベル */ }; -byte iv[AES_BLOCK_SIZE] = { /* AES IV */ }; - -byte plainText[AES_BLOCK_SIZE] = { /* 平文 */ }; -byte cipherText[AES_BLOCK_SIZE]; - -wc_AesInit(&aes, NULL, WOLFHSM_DEV_ID); - -/* IVは鍵と別に設定する必要がある */ -wc_AesSetIV(&aes, iv); - -/* この鍵は使用前の任意のタイミングでキャッシュできます。ここでは例として示しています */ -wh_Client_KeyCache(clientCtx, 0, label, sizeof(label), key, sizeof(key), &keyId); - -wh_Client_SetKeyAes(&aes, keyId); - -wc_AesCbcEncrypt(&aes, &cipherText, &plainText, sizeof(plainText)); - -/* 鍵の削除は任意です。鍵はキャッシュまたはNVMに保存され、wolfCryptで使用できます */ -wh_Client_KeyEvict(clientCtx, keyId); - -wc_AesFree(&aes); -``` - -暗号化をクライアントのローカルで実行したい場合は、`wc_AesInit()`に`INVALID_DEVID`を渡します。 - -```c -wc_AesInit(&aes, NULL, INVALID_DEVID); -``` - -より詳しい使用方法の説明やサポートされている暗号化アルゴリズムの詳細なリストをお求めでしたら、[wolfSSLマニュアル](https://www.wolfssl.com/documentation/manuals/jp/wolfssl/)内のwolfCrypt APIリファレンスをご参照ください。 - -### CMAC - -キャッシュされた鍵を使用するCMAC操作の場合、CMACハッシュと検証操作を1回の関数呼び出しで実行するための、wolfHSM固有の別の関数を呼び出す必要があります。 -関数が呼び出されたときにクライアントが鍵を提供できる場合は、通常の`wc_AesCmacGenerate_ex`と`wc_AesCmacVerify_ex`を使用できます。 -しかし、事前にキャッシュされたキーを使用するためには、`wh_Client_AesCmacGenerate`と`wh_Client_AesCmacVerify`を使用する必要があります。 -ワンショットではない関数の`wc_InitCmac_ex`、`wc_CmacUpdate`、`wc_CmacFinal`は、クライアント側の鍵・事前にキャッシュされた鍵のどちらでも使用できます。 -これらの関数でキャッシュされたキーを使用するには、呼び出し元は`NULL`キーパラメータを渡し、`wh_Client_SetKeyCmac`を使用して適切なkeyIdを設定する必要があります。 - -## AUTOSAR SHE API - -(本章は後日提供予定です。) diff --git a/wolfHSM/src-ja/chapter06.md b/wolfHSM/src-ja/chapter06.md deleted file mode 100644 index b16a8095..00000000 --- a/wolfHSM/src-ja/chapter06.md +++ /dev/null @@ -1,25 +0,0 @@ -# サーバライブラリ - -wolfHSMサーバーライブラリは、暗号ライブラリwolfCryptのサーバー側実装です。 -アプリケーションが暗号化操作を専用サーバーにオフロードするためのインターフェイスを提供します。専用サーバーでは wolfHSMサーバーソフトウェアを実行します。これにより、アプリケーションは暗号化キーを管理したり、ローカルで操作を実行したりすることなく、暗号化操作を実行できます。 - -## ことはじめ - -(本章は後日提供予定です。) - -## 内部構造 - -(本章は後日提供予定です。) - -## APIリファレンス - -(本章は後日提供予定です。) - -## 鍵管理 - -(本章は後日提供予定です。) - -## 暗号 - -wolfHSMはすべての暗号操作にwolfCryptを使用します。つまり、wolfHSMはwolfCyptでサポートされている任意のアルゴリズムをオフロードし、wolfHSMサーバーで実行できます。これには、中国政府が義務付けたShāngMì暗号(SM2、SM3、SM4)や、Kyber、LMS、XMSS などの耐量子暗号アルゴリズムも含まれます。 - diff --git a/wolfHSM/src-ja/chapter07.md b/wolfHSM/src-ja/chapter07.md deleted file mode 100644 index 9e761406..00000000 --- a/wolfHSM/src-ja/chapter07.md +++ /dev/null @@ -1,463 +0,0 @@ -# カスタマイズ - -wolfHSMは、ビルド時のオプションやユーザー定義のコールバックを通じて複数のカスタマイズポイントを提供しています。 -これにより、コアライブラリのコードを変更することなく、幅広いユースケースや環境に合わせて調整できます。 -本章では、wolfHSMで利用可能なカスタマイズオプションの概要を説明します。内容は以下の通りです。 - -- ライブラリ設定: ライブラリの特定の機能を有効化または無効化するためのコンパイル時オプション -- DMAコールバック: クライアントのメモリに直接アクセスする前後で操作を実行するために、サーバーに登録できるカスタムコールバック -- DMAアドレス許可リスト: クライアントのアクセスを特定のメモリ領域に制限するためのサーバーの仕組み -- カスタムコールバック: デフォルトのHSM機能では対応していない特定の操作を実行するために、サーバーに登録してクライアントから呼び出すことができるカスタムコールバック - -## ライブラリ設定 - -wolfHSMライブラリには、コンパイル時の定義を通じてオン/オフを切り替えることができる多くのビルドオプションがあります。 -これらの設定マクロは、`wh_config.h`という名前の設定ヘッダーファイルで定義されることを想定しています。 -このファイルはwolfHSMを使用するアプリケーションによって定義され、コンパイラのインクルードパスのディレクトリ内に配置される必要があります。 - -サンプルの`wh_config.h`は動作確認済みの設定として、すべてのwolfHSMポートに同梱しています。 - -`wh_config.h`で定義可能なwolfHSMの設定項目の完全なリストについては、[APIドキュメント](appendix01.md)をご参照ください。 - -## DMAコールバック - -wolfHSMのダイレクトメモリアクセス(DMA)コールバック機能は、クライアントのメモリに直接アクセスする前後でカスタム操作を行うためのフックをサーバー側に提供します。 -これは新しい共有メモリアーキテクチャへの移植を行う際によく必要とされます。この機能は特に、クライアントとサーバーのメモリ間の一貫性を確保するために、キャッシュの無効化やアドレス変換、その他のカスタムメモリ操作などの特定のアクションをサーバーが実行する必要がある場合に有用です。 - -コールバックは`wh_Server_DmaRegisterCb32()`および`wh_Server_DmaRegisterCb64()`関数を使用してサーバーに登録できます。 -これによって提供されたコールバックは、サーバーコンテキストのすべてのDMA操作にバインドされます。 - -32ビットと64ビットのアドレスを処理するための別々のコールバック関数が必要で、これらはそれぞれ32ビットと64ビットのクライアントDMA API関数に対応します。 -コールバック関数は`whServerDmaClientMem32Cb`および`whServerDmaClientMem64Cb`型で、以下のように定義しています。 - -```c -typedef int (*whServerDmaClientMem32Cb)(struct whServerContext_t* server, - uint32_t clientAddr, void** serverPtr, - uint32_t len, whServerDmaOper oper, - whServerDmaFlags flags); -typedef int (*whServerDmaClientMem64Cb)(struct whServerContext_t* server, - uint64_t clientAddr, void** serverPtr, - uint64_t len, whServerDmaOper oper, - whServerDmaFlags flags); -``` - -DMAコールバック関数は以下の引数を受け取ります: - -- `server`: サーバーコンテキストへのポインタ -- `clientAddr`: アクセスされるクライアントのメモリアドレス -- `serverPtr`: サーバーのメモリアドレス(これもポインタ)へのポインタ。コールバックは必要な変換/再マッピングを適用した後にこれを設定します。 -- `len`: 要求されたメモリ操作のバイト単位の長さ -- `oper`: 変換されたサーバーアドレスに対して実行されようとしているメモリ操作(注入ポイントについては次のセクションで説明)の種類 -- `flags`: メモリ操作の追加フラグ。将来的に使用することを見越して確保している領域です。 - -コールバックは成功時に`WH_ERROR_OK`を、エラーが発生した場合はエラーコードを返す必要があります。 -コールバックが失敗した場合、サーバーはエラーコードをクライアントに伝達させます。 - -### コールバックの位置 - -DMAコールバックは、サーバーのメモリアクセスの周りの4つの異なるポイントで行われます: - -- 読み取り前: クライアントメモリからデータを読み取る前にコールバックが呼び出されます。サーバーはコールバックを使用して、アドレス変換やキャッシュの無効化など、必要な読み取り前の操作を実行する必要があります。 -- 読み取り後: クライアントメモリからデータを読み取った後にコールバックが呼び出されます。サーバーはコールバックを使用して、キャッシュの同期など、必要な読み取り後の操作を実行する必要があります。 -- 書き込み前: クライアントメモリにデータを書き込む前にコールバックが呼び出されます。サーバーはコールバックを使用して、アドレス変換やキャッシュの無効化など、必要な書き込み前の操作を実行する必要があります。 -- 書き込み後: クライアントメモリにデータを書き込んだ後にコールバックが呼び出されます。サーバーはコールバックを使用して、キャッシュの同期など、必要な書き込み後の操作を実行する必要があります。 - -コールバックが呼び出されるポイントは、`oper`引数を通じてコールバックに渡されます。 -具体的には、以下のいずれかの値です。 - -```c -typedef enum { - WH_SERVER_DMA_OPER_PRE_READ, /* 読み取り前の操作 */ - WH_SERVER_DMA_OPER_POST_READ, /* 読み取り後の操作 */ - WH_SERVER_DMA_OPER_PRE_WRITE, /* 書き込み前の操作 */ - WH_SERVER_DMA_OPER_POST_WRITE /* 書き込み後の操作 */ -} whServerDmaOper; -``` - -これにより、コールバックは`oper`の値で`switch`文を使用し、実行されるメモリ操作の種類に基づいてカスタムロジックを実行できます。 -以下にDMAコールバックの実装例を示します。 - -```c -#include "wolfhsm/wh_server.h" -#include "wolfhsm/wh_error.h" - -/* 32ビットクライアントアドレス用のDMAコールバック実装例 */ -int myDmaCallback32(whServerContext* server, uint32_t clientAddr, - void** xformedCliAddr, uint32_t len, - whServerDmaOper oper, whServerDmaFlags flags) -{ - /* 必要に応じてクライアントアドレスをサーバーのアドレス空間に変換、例:memmap() */ - *xformedCliAddr = (void*)clientAddr; /* 変換を実行 */ - - switch (oper) { - case WH_DMA_OPER_CLIENT_READ_PRE: - /* 読み取り前の操作をここに記述、例:キャッシュの無効化 */ - break; - case WH_DMA_OPER_CLIENT_READ_POST: - /* 読み取り後の操作をここに記述 */ - break; - case WH_DMA_OPER_CLIENT_WRITE_PRE: - /* 書き込み前の操作をここに記述 */ - break; - case WH_DMA_OPER_CLIENT_WRITE_POST: - /* 書き込み後の操作をここに記述、例:キャッシュのフラッシュ */ - break; - default: - return WH_ERROR_BADARGS; - } - - return WH_ERROR_OK; -} -``` - -### コールバックの登録 - -コールバックは、いつでもサーバーコンテキストに登録できます。 -初期化時にはサーバー設定構造体を通じて、初期化後にはコールバック登録関数を使用して実施します。 - -初期化時にコールバックを登録するには、コールバック関数をサーバー設定構造体内のDMA設定構造体に含める必要があります。 -なお、コールバック関数の設定は任意であり、使用しないコールバックは`NULL`と設定できます。 - -```c -#include "wolfhsm/wh_server.h" - -/* DMA32コールバックを持つサーバー設定構造体の初期化とサーバーの初期化の例 */ -int main(void) -{ - whServerDmaConfig dmaCfg = {0}; - dmaCfg.dma32Cb = myDmaCallback32; - - - whServerConfig serverCfg = { - .dmaCfg = dmaCfg, - - /* 簡潔にするため、その他の設定は省略 */ - }; - - whServerContext serverCtx; - - wh_Server_Init(&serverCtx, &serverCfg); - - /* サーバーアプリケーションのロジック */ -} -``` - -初期化後にコールバックを登録する際は、以下のように関数を呼び出します。 - -```c -#include "wolfhsm/wh_server.h" - -int main(void) -{ - whServerConfig serverCfg = { /* サーバーの設定 */ }; - - whServerContext serverCtx; - - wh_Server_Init(&serverCtx, &serverCfg); - - /* 上で定義したコールバックを登録 */ - wh_Server_DmaRegisterCb32(&serverCtx, myDmaCallback32); - - /* サーバーアプリケーションのロジック */ -} -``` - -## DMAアドレス許可リスト - -wolfHSMは、クライアントのDMAアドレスに対する「許可リスト」も公開しています。 -これにより、クライアントによるアクセスを事前に設定した特定のメモリ領域に制限できます。 -この機能は、サーバーが不正なアクセスを拒否するため、あるいはクライアントが安全にアクセスできるメモリにのみアクセスできるようにするために有用です。 -例えば、複数のコアでそれぞれクライアントが実行されるマルチコアシステムでは、クライアントは他のクライアントのメモリ領域にアクセスできないようにすべきであり、暗号化キーなどの機密情報を含む可能性のあるサーバーメモリを読み出すこともできないようにすべきです。 - -ただしこの許可リスト機能は、デバイス固有のメモリ保護メカニズムの上に第二層の保護として機能することを意図しています。 -よって、不正なメモリアクセスを防ぐ第一の防衛線とは考えるべきではありません。 -ユーザーはアプリケーションを厳密に分離し、HSMコアと関連メモリをシステムの残りの部分から分離するために必要な、デバイス固有のメモリ保護メカニズムを設定することが不可欠です。 - -### 許可リストへの登録 - -DMAコールバックと同様に、いつでもサーバーコンテキストに登録できます。 - -初期化時にリストを登録するには、サーバー設定構造体内のDMA設定構造体にリストを設定する必要があります。 - -```c -#include "wolfhsm/wh_server.h" -#include "wolfhsm/wh_error.h" - -/* 許可されるメモリ領域を定義 */ -const whServerDmaAddrAllowList allowList = { - .readList = { - {(void*)0x20001000, 0x100}, /* 0x20001000から0x200010FFまでの読み取りを許可 */ - {(void*)0x20002000, 0x200}, /* 0x20002000から0x200021FFまでの読み取りを許可 */ - }, - .writeList = { - {(void*)0x20003000, 0x100}, /* 0x20003000から0x200030FFまでの書き込みを許可 */ - {(void*)0x20004000, 0x200}, /* 0x20004000から0x200041FFまでの書き込みを許可 */ - }, -}; - -int main() -{ - whServerConfig config; - - - whServerDmaConfig dmaCfg = {0}; - dmaCfg.allowList = &allowList; - - whServerConfig serverCfg = { - .dmaCfg = dmaCfg, - /* 簡潔にするため、その他の設定は省略 */ - }; - - whServerContext server; - - wh_Server_Init(&server, &config); - - /* これでサーバーは許可リストで設定されました */ - /* その他のサーバー操作を実行 */ - - /* 許可リストは、サーバー設定構造体にリストが存在しない場合、 - * 初期化後に以下を使用して登録することもできます。 - * - * wh_Server_DmaRegisterAllowList(&server, &allowList); - */ -} -``` - -登録後、クライアントからサーバーに要求されるすべてのDMA操作は、許可リストと照合してチェックされます。 -クライアントが許可リストにないメモリ領域にアクセスしようとすると、サーバーはクライアントにエラーを返し、その操作は実行されません。 - -## カスタムコールバック - -wolfHSMのカスタムコールバック機能により、開発者はサーバー上にカスタムコールバック関数を登録することで、ライブラリの機能を拡張できます。 -これらのコールバックは、HSMが対応していない特定の操作を実行するために、クライアントから呼び出すことができます。 -例えば、周辺ハードウェアの有効化や無効化、カスタムの監視や認証ルーチンの実装、追加コアのセキュアブートのステージングなどです。 - -### サーバー側 - -サーバーは、特定の操作を定義するカスタムコールバック関数を登録できます。これらの関数は`whServerCustomCb`型である必要があります。 - -```c -/* wh_server.h */ - -/* サーバーのカスタムコールバックの型定義 */ -typedef int (*whServerCustomCb)( - whServerContext* server, /* 送信元のサーバーコンテキストを指すポインタ */ - const whMessageCustomCb_Request* req, /* クライアントからコールバックへのリクエスト */ - whMessageCustomCb_Response* resp /* コールバックからクライアントへのレスポンス */ -); -``` - -サーバーのカスタムコールバック関数は、サーバーのカスタムコールバックディスパッチテーブルのインデックスに対応する一意の識別子(ID)に関連付けられます。 -クライアントは呼び出しを要求する際に、このIDでコールバックを参照します。 - -カスタムコールバックは、コールバック関数に渡される`whMessageCustomCb_Request`引数を通じて、値またはポインタ参照(共有メモリシステムで有用)によってクライアントから渡されたデータにアクセスできます。 -コールバックは入力データに基づいて処理を行い、`whMessageCustomCb_Response`引数を通じてクライアントに返される出力データを生成できます。 -入力/出力クライアントデータの送受信はwolfHSMによって外部で処理されるため、カスタムコールバックでこれらを処理する必要はありません。 -レスポンス構造体には、クライアントに伝播させるためのエラーコードとリターンコードのフィールドも含まれています。 -エラーコードはコールバックによって設定され、リターンコードはカスタムコールバックからの戻り値に設定されます。 - -### クライアント側 - -クライアントは、これらのカスタムコールバックを呼び出すためのリクエストをサーバーに送信できます。 -APIは、クライアントAPIの他の関数と同様のリクエスト関数とレスポンス関数を提供します。 -クライアントはカスタムリクエスト構造体のインスタンスを宣言し、カスタムデータを設定し、`wh_Client_CustomCbRequest()`を使用してサーバーに送信する必要があります。 -サーバーのレスポンスは`wh_Client_CustomCbResponse()`を使用してポーリングすることができ、正常に受信された場合、レスポンスデータは出力の`whMessageCustomCb_Response()`に格納されます。 - -クライアントは`wh_Client_CustomCheckRegistered()`系の関数を使用して、特定のコールバックIDの登録状態を確認することもできます。 -この関数は、指定されたコールバックIDがサーバーの内部コールバックテーブルに登録されているかどうかをサーバーに問い合わせます。 -サーバーは登録状態を示すtrueまたはfalseで応答します。 - -### カスタムメッセージ - -クライアントは、カスタムリクエストおよびレスポンスメッセージ構造体を通じて、カスタムコールバックにデータを渡したり、データを受け取ったりできます。 -これらのカスタムリクエストおよびレスポンスメッセージは、一意のID、タイプ指示子、およびデータペイロードを含むように構成されています。 -IDはサーバーのコールバックテーブルのインデックスに対応します。タイプフィールドは、データペイロードをどのように解釈すべきかをカスタムコールバックに示します。 -データペイロードは固定サイズのデータバッファで、クライアントは任意の方法で使用できます。レスポンス構造体には、上述のエラーコード値が追加されています。 - -```c -/* カスタムサーバーコールバックへのリクエストメッセージ */ -typedef struct { - uint32_t id; /* 登録されたコールバックの識別子 */ - uint32_t type; /* whMessageCustomCb_Type */ - whMessageCustomCb_Data data; -} whMessageCustomCb_Request; - -/* カスタムサーバーコールバックからのレスポンスメッセージ */ -typedef struct { - uint32_t id; /* 登録されたコールバックの識別子 */ - uint32_t type; /* whMessageCustomCb_Type */ - int32_t rc; /* カスタムコールバックからの戻り値。errが0でない場合は無効 */ - int32_t err; /* wolfHSM固有のエラー。errが0でない場合、rcは無効 */ - whMessageCustomCb_Data data; -} whMessageCustomCb_Response; -``` - -### カスタムデータ側の定義 - -カスタムデータ型は`whMessageCustomCb_Data`共用体を使用して定義することができます。 -この共用体には一般的なデータ型(例:dma32、dma64)用の便利な定義済み構造体と、ユーザー定義のスキーマ用の生データバッファ(buffer)が用意されています。 -クライアントはリクエストの`type`フィールドを通じて、サーバーコールバックがユニオン内のデータをどのように解釈すべきかを指示できます。 -wolfHSMは最初の数個のタイプインデックスを内部使用のために予約し、残りのタイプ値はカスタムクライアントタイプで使用可能です。 - -### カスタムコールバックの例 - -ここでは、組み込みのDMAスタイルのアドレス指定タイプを使用する1つのリクエストと、カスタムユーザー定義タイプを使用する2つのリクエストの、合計3種類のクライアントリクエストを処理できるカスタムコールバックを実装します。 - -まず、クライアントとサーバー間で共有される共通のメッセージを定義します。 - -```c -/* my_custom_cb.h */ - -#include "wolfhsm/wh_message_customcb.h" - -#define MY_CUSTOM_CB_ID 0 - -enum { - MY_TYPE_A = WH_MESSAGE_CUSTOM_CB_TYPE_USER_DEFINED_START, - MY_TYPE_B, -} myUserDefinedTypes; - -typedef struct { - int foo; - int bar; -} myCustomCbDataA; - -typedef struct { - int noo; - int baz; -} myCustomCbDataB; -``` - -サーバー側では、リクエストを処理する前に、コールバックを定義し、サーバーコンテキストに登録する必要があります。 -なお、コールバックの登録は必ずしも最初のリクエストの処理前である必要はありません。いつでも行うことができます。 - -```c -#include "wolfhsm/wh_server.h" -#include "my_custom_cb.h" - -int doWorkOnClientAddr(uint8_t* addr, uint32_t size) { - /* タスクを実行 */ -} - -int doWorkWithTypeA(myCustomTypeA* typeA) { - /* タスクを実行 */ -} - -int doWorkWithTypeB(myCustomTypeB* typeB) { - /* タスクを実行 */ -} - -static int customServerCb(whServerContext* server, - const whMessageCustomCb_Request* req, - whMessageCustomCb_Response* resp) -{ - int rc; - - resp->err = WH_ERROR_OK; - - /* DMAリクエストを検出して処理 */ - if (req->type == WH_MESSAGE_CUSTOM_CB_TYPE_DMA32) { - uint8_t* clientPtr = (uint8_t*)((uintptr_t)req->data.dma32.client_addr); - size_t clientSz = req->data.dma32.client_sz; - - if (clientPtr == NULL) { - resp->err = WH_ERROR_BADARGS; - } - else { - rc = doWorkOnClientAddr(clientPtr, clientSz); - } - } - else if (req->type == MY_TYPE_A) { - myCustomCbDataA *data = (myCustomCbDataA*)((uintptr_t)req->data.data); - rc = doWorkWithTypeA(data); - /* 必要に応じてエラーコードを設定 */ - if (/* エラー条件 */) { - resp->err = WH_ERROR_ABORTED; - } - } - else if (req->type == MY_TYPE_B) { - myCustomCbDataB *data = (myCustomCbDataB)((uintptr_t)req->data.data); - rc = doWorkWithTypeB(data); - /* 必要に応じてエラーコードを設定 */ - if (/* エラー条件 */) { - resp->err = WH_ERROR_ABORTED; - } - } - - return rc; -} - - -int main(void) { - - whServerContext serverCtx; - - whServerConfig serverCfg = { - /* サーバーの設定 */ - }; - - wh_Server_Init(&serverCtx, &serverCfg); - - wh_Server_RegisterCustomCb(&serverCtx, MY_CUSTOM_CB_ID, customServerCb)); - - /* サーバーリクエストを処理(簡略化) */ - while (1) { - wh_Server_HandleRequestMessage(&serverCtx); - } - -} -``` - -これで、クライアントはカスタムコールバックの登録を確認し、リモートで呼び出すことができるようになりました。 - -```c -#include "wh_client.h" -#include "my_custom_cb.h" - -whClientContext clientCtx; -whClientConfig clientCfg = { - /* クライアントの設定 */ -}; - -whClient_Init(&clientCtx, &clientCfg); - -bool isRegistered = wh_Client_CustomCheckRegistered(&client, MY_CUSTOM_CB_ID); - -if (isRegistered) { - uint8_t buffer[LARGE_SIZE] = {/* データ */}; - myCustomCbDataA typeA = {/* データ */}; - myCustomCbDataB typeB = {/* データ */}; - - whMessageCustomCb_Request req = {0}; - whMessageCustomCb_Request resp = {0}; - - /* 組み込みDMAタイプでカスタムリクエストを送信 */ - req.id = MY_CUSTOM_CB_ID; - req.type = WH_MESSAGE_CUSTOM_CB_TYPE_DMA32; - req.data.dma32.client_addr = (uint32_t)((uintptr_t)&data); - req.data.dma32.client_sz = sizeof(data); - wh_Client_CustomCbRequest(clientCtx, &req); - wh_Client_CustomCbResponse(clientCtx, &resp); - /* レスポンスを使用した処理を実行 */ - - /* ユーザー定義タイプでカスタムリクエストを送信 */ - memset(req, 0, sizeof(req)); - req.id = MY_CUSTOM_CB_ID; - req.type = MY_TYPE_A; - memcpy(&req.data.data, typeA, sizeof(typeA)); - wh_Client_CustomCbRequest(clientCtx, &req); - wh_Client_CustomCbResponse(clientCtx, &resp); - /* レスポンスを使用した処理を実行 */ - - /* 別のユーザー定義タイプでカスタムリクエストを送信 */ - memset(req, 0, sizeof(req)); - req.id = MY_CUSTOM_CB_ID; - req.type = MY_TYPE_B; - memcpy(&req.data.data, typeA, sizeof(typeB)); - wh_Client_CustomCbRequest(clientCtx, &req); - wh_Client_CustomCbResponse(clientCtx, &resp); - /* レスポンスを使用した処理を実行 */ -} - -``` - diff --git a/wolfHSM/src-ja/chapter08.md b/wolfHSM/src-ja/chapter08.md deleted file mode 100644 index 1e67ec77..00000000 --- a/wolfHSM/src-ja/chapter08.md +++ /dev/null @@ -1,83 +0,0 @@ -# ポーティング - -このセクションでは、wolfHSMのポーティングに関連する資料と情報を提供することを目的としています。 -次の内容についてご説明いたします。 - -- 概要 -- 対応状況 -- ポーティングインタフェース - -## 概要 - -wolfHSM自体には特定のハードウェアと対話するためのコードは含まれておらず、単体では実行できません。 wolfHSMをデバイスで実行するには、サーバ アプリケーションがクライアントと通信して実行できるように、必要なハードウェアドライバーと抽象化レイヤーを使用してライブラリを構成する必要があります。具体的には、次の要素が必要です。 - -- サーバーアプリケーションの起動とハードウェアの初期化 -- サーバーにおけるwolfCrypt構成 -- サーバーの不揮発性メモリ構成 -- サーバーとクライアントのトランスポート構成 -- サーバーとクライアントの接続処理 - -これらの要件を提供し、サーバーAPIを起動可能なアプリケーションにラップするコードを、wolfHSM「ポート」と呼んでいます。 - -wolfHSMの公式ポートは、サポートされているさまざまなアーキテクチャ用に提供しています。それぞれのポートには次のものが含まれます。 - -- スタンドアロンリファレンスサーバーアプリケーション: このアプリケーションは、HSMコアで実行され、すべての安全な操作を処理することを目的としています。すぐに使用できる状態で完全に機能しますが、エンドユーザーがカスタマイズして追加のユースケースをサポートすることもできます。 -- クライアントライブラリ: このライブラリは、ユーザーアプリケーションにリンクして、サーバーとの通信を容易にします。 - -## 対応状況 - -### Infineon Aurix TC3XX - -このポートの配布はベンダーによって制限されています。ご入用の方は、info@wolfssl.jp までお問い合わせください。 - -**Infineon Aurix TC3xx** - -- 最大6つのの300MHz TriCoreアプリケーションコア -- 1つの100MHz ARM Cortex M3 HSMコア -- 暗号化オフロード: TRNG、AES128、ECDSA、ED25519、SHA - -### ST SPC58NN - -このポートの配布はベンダーによって制限されています。ご入用の方は、info@wolfssl.jp までお問い合わせください。 - -**ST SPC58NN** - -- 3つの200MHz e200z4256 PowerPC アプリケーションコア -- 1つの100MHz e200z0 PowerPC HSMコア (NVM付き) -- 暗号化オフロード: TRNG、AES128 - -### POSIX - -POSIXポートは、さまざまなwolfHSM抽象化の完全機能実装を提供します。これを使用すると、さまざまなハードウェア抽象化に期待される正確な機能をよりよく理解できます。 - -POSIXポートは以下を提供します。 - -- メモリバッファトランスポート -- TCPトランスポート -- Unixドメイントランスポート -- RAMベースおよびファイルベースのNVMフラッシュシミュレーター - -### Skeleton - -スケルトンポートのソースコードは、将来のハードウェア/プラットフォーム ポートの開始点として使用できる非機能レイアウトを提供します。各関数には、基本的な説明と予想されるフローがエラーケースとともに説明されているため、さまざまな環境において一貫した結果を得ることができます。 - -スケルトンポートは、次のスタブ実装を提供します。 - -- トランスポートコールバック -- NVMフラッシュコールバック -- 暗号処理コールバック - -## ポーティングインタフェース - -ポートはハードウェア固有のインターフェースを実装する必要があります。 - -- NVM フラッシュ インターフェース - -暗号化ハードウェア - -- TRNG、鍵、公開鍵暗号・共通鍵暗号 - -プラットフォームインターフェース - -- ブートシーケンス、アプリケーションコアリセット、メモリ制限 -- ポートと構成はコンパイル時に指定します。 diff --git a/wolfHSM/src-ja/wolfHSM-diagram.png b/wolfHSM/src-ja/wolfHSM-diagram.png deleted file mode 100644 index f0db54df..00000000 Binary files a/wolfHSM/src-ja/wolfHSM-diagram.png and /dev/null differ diff --git a/wolfHSM/src/appendix01.md b/wolfHSM/src/appendix01.md deleted file mode 100644 index 5775054a..00000000 --- a/wolfHSM/src/appendix01.md +++ /dev/null @@ -1 +0,0 @@ -# wolfHSM API reference diff --git a/wolfHSM/src/chapter01.md b/wolfHSM/src/chapter01.md deleted file mode 100644 index d35610c2..00000000 --- a/wolfHSM/src/chapter01.md +++ /dev/null @@ -1,17 +0,0 @@ -# Introduction - -This manual is written as a technical guide to the wolfHSM embedded hardware security module library. It -will explain how to build and get started with wolfHSM, provide an overview of build -options, features, portability enhancements, support, and much more. - -You can find the PDF version of this document [here](https://www.wolfssl.com/documentation/manuals/wolfhsm/wolfHSM-Manual.pdf). - -## Why Choose wolfHSM? - -Automotive HSMs (Hardware Security Modules) dramatically improve the security of cryptographic keys and processing. They achieve this by isolating signature verification and cryptographic execution, the very foundations of security, into physically independent processors. These HSMs are not just recommended, but often mandatory for ECUs that demand robust security. In line with this, wolfSSL has seamlessly integrated our popular, rigorously tested, and industry-leading cryptographic library to operate in widely used Automotive HSMs such as Aurix Tricore TC3XX. WolfHSM, with its sole dependency on wolfCrypt, ensures portability across almost any runtime environment. It also facilitates a user-friendly client interface, allowing direct utilization of wolfCrypt APIs. - -wolfHSM provides a portable and open-source abstraction to hardware cryptography, non-volatile memory, and isolated secure processing, maximizing security and performance for ECUs. By integrating the wolfCrypt software crypto engine on hardware HSMs like Infineon Aurix Tricore TC3XX, Chinese-mandated government algorithms like SM2, SM3, and SM4 are available. Additionally, Post Quantum Cryptography algos like Kyber, LMS, XMSS, and others are easily made available to automotive users to meet customer requirements. At the same time, when hardware cryptographic processing is available on the HSM, we consume it to enhance performance. - -wolfBoot is a mature, portable, secure bootloader solution designed for bare-metal bootloaders and equipped with failsafe NVM controls. It offers comprehensive firmware authentication and update mechanisms, leveraging a minimalistic design and a tiny HAL API, which makes it fully independent from any operating system or bare-metal application. wolfBoot efficiently manages the flash interface and pre-boot environment, accurately measures and authenticates applications, and utilizes low-level hardware cryptography as needed. wolfBoot can use the wolfHSM client to support HSM-assisted application core secure boot. Additionally, wolfBoot can run on the HSM core to ensure the HSM server is intact, offering a secondary layer of protection. This setup ensures a secure boot sequence, aligning well with the booting processes of HSM cores that rely on NVM support. - - diff --git a/wolfHSM/src/chapter02.md b/wolfHSM/src/chapter02.md deleted file mode 100644 index a6810c02..00000000 --- a/wolfHSM/src/chapter02.md +++ /dev/null @@ -1,90 +0,0 @@ -# Overview - -wolfHSM is a software framework that provides a unified API for HSM operations -such as cryptographic operations, key management, and non-volatile storage. -It is designed to improve portability of code related to HSM applications, -easing the challenge of moving between hardware with enhanced security -features without being tied to any vendor-specific library calls. It -dramatically simplifies client applications by allowing direct use of wolfCrypt -APIs, with the library automatically offloading all sensitive cryptographic -operations to the HSM core as remote procedure calls with no additional logic -required by the client app. - -Although initially targeted to automotive-style HSM-enabled microcontrollers, -wolfHSM provides an extensible solution to support future capabilities of -platforms while still supporting standardized interfaces and protocols such as -PKCS11 and AUTOSAR SHE. It has no external dependencies other than wolfCrypt and -is portable to almost any runtime environment. - -## Features - -- Secure non-volatile object storage with user-based permissions -- Cryptographic key management with support for hardware keys -- Hardware cryptographic support for compatible devices -- Fully asynchronous client API -- Flexible callback architecture enables custom use cases without modifying library -- Use wolfCrypt APIs directly on client, with automatic offload to HSM core -- Image manager to support chain of trust -- Integration with AUTOSAR -- Integration with SHE+ -- PKCS11 interface available -- TPM 2.0 interface available -- Secure OnBoard Communication (SecOC) module integration available -- Certificate handling -- Symmetric and Asymmetric keys and cryptography -- Supports "crypto agility" by providing every algorithm implemented in wolfCrypt, not just those implemented by your silicon vendor -- FIPS 140-3 available - -## Architecture - -wolfHSM employs a client-server architecture where the server runs in a trusted -and secure environment (typically on a secure coprocessor) and the client is a library -that can be linked against user applications. This architecture ensures that -sensitive cryptographic operations and key management are handled securely - within the server, while the client library abstracts away the lower level -communication with the server. - -- Server: The server component of wolfHSM is a standalone application that runs - on the HSM core. It handles cryptographic operations, key management, and - non-volatile storage within a secure environment. The server is responsible - for processing requests from clients and returning the results. - -- Client: The client component of wolfHSM is a library that can be linked - against user applications. It provides APIs for sending requests to the - server and receiving responses. The client abstracts the complexities of - communication and ensures that the application can interact with the HSM - securely and efficiently. - -## Ports - -wolfHSM itself is not executable and it does not contain any code to interact with any specific hardware. In order for wolfHSM to run on a specific device, the library must be configured with the necessary hardware drivers and abstraction layers so that the server application can run and communicate with the client. Specifically, getting wolfHSM to run on real hardware requires the implementation of the following: - -- Server application startup and hardware initialization -- Server wolfCrypt configuration -- Server non-volatile memory configuration -- Server and client transport configuration -- Server and client connection handling - -The code that provides these requirements and wraps the server API into a bootable application is collectively referred to as a wolfHSM "port". - -Official ports of wolfHSM are provided for various supported architectures, with each port providing the implementation of the wolfHSM abstractions tailored to the specific device. Each port contains: - -- Standalone Reference Server Application: This application is meant to run on the HSM core and handle all secure operations. It comes fully functional out-of-the-box but can also be customized by the end user to support additional use cases -- Client Library: This library can be linked against user applications to facilitate communication with the server - -### Supported Ports - -wolfHSM has supported ports for the following devices/environments: - -- POSIX runtime -- ST Micro SPC58N\* -- Infineon Aurix TC3xx\* -- Infineon Aurix TC4xx\* (coming soon) -- Infineon Traveo T2G\* (coming soon) -- Renesas RH850\* (coming soon) -- Renesas RL78\* (coming soon) -- NXP S32\* (coming soon) - -With additional ports on the way. - -\* These ports, unfortunately, require an NDA with the silicon vendor to obtain any information about the HSM core. Therefore, the wolfHSM ports for these platforms are not public and are only available to qualified customers. If you wish to access a restricted wolfHSM port, please contact us at support@wolfssl.com. diff --git a/wolfHSM/src/chapter03.md b/wolfHSM/src/chapter03.md deleted file mode 100644 index 38de120d..00000000 --- a/wolfHSM/src/chapter03.md +++ /dev/null @@ -1,200 +0,0 @@ -# Getting Started With wolfHSM - -The most common use case for wolfHSM is adding HSM-enabled functionality to an existing application that runs on one of the application cores of a multi-core device with an HSM coprocessor. - -The first step required to run wolfHSM on a device is to follow the steps in the specific wolfHSM port to get the reference server running on the HSM core. Once the wolfHSM server app is loaded on the device and boots, client applications can link against the wolfHSM client library, configure an instance of the wolfHSM client structure, and interact with the HSM through the wolfHSM client API and through the wolfCrypt API. - -Each wolfHSM port contains a client demo app showing how to set up the default communication channel and interact with the server. The server reference implementation can also be customized through [server callbacks](./chapter07.md) to extend its functionality, which can be invoked through client requests. - -## Basic Client Configuration - -Configuring a wolfHSM client involves allocating a client context structure and initializing it with a valid client configuration that enables it to communicate with a server. - -The client context structure `whClientContext` holds the internal state of the client and its communication with the server. All client APIs take a pointer to the client context. - -The client configuration structure holds the communication layer configuration (`whCommClientConfig`) that will be used to configure and initialize the context for the server communication. The `whCommClientConfig` structure binds an actual transport implementation (either built-in or custom) to the abstract comms interface for the client to use. - -The general steps to configure a client are: - -1. Allocate and initialize a transport configuration structure, context, and callback implementation for the desired transport -2. Allocate comm client configuration structure and bind it to the transport configuration from step 1 so it can be used by the client -3. Allocate and initialize a client configuration structure using the comm client configuration in step 2 -4. Allocate a client context structure -5. Initialize the client with the client configuration by calling `wh_Client_Init()` -6. Use the client APIs to interact with the server - -Here is a bare-minimum example of configuring a client application to use the built-in shared memory transport to send an echo request to the server. - -```c -#include /* for memcmp() */ -#include "wolfhsm/client.h" /* Client API (includes comm config) */ -#include "wolfhsm/wh_transport_mem.h" /* transport implementation */ - -/* Step 1: Allocate and initialize the shared memory transport configuration */ -/* Shared memory transport configuration */ -static whTransportMemConfig transportMemCfg = { /* shared memory config */ }; -/* Shared memory transport context (state) */ -whTransportMemClientContext transportMemClientCtx = {0}; -/* Callback structure that binds the abstract comm transport interface to - * our concrete implementation */ -whTransportClientCb transportMemClientCb = {WH_TRANSPORT_MEM_CLIENT_CB}; - -/* Step 2: Allocate client comm configuration and bind to the transport */ -/* Configure the client comms to use the selected transport configuration */ -whCommClientConfig commClientCfg = { - .transport_cb = transportMemClientCb, - .transport_context = (void*)transportMemClientCtx, - .transport_config = (void*)transportMemCfg, - .client_id = 123, /* unique client identifier */ -}; - -/* Step 3: Allocate and initialize the client configuration */ -whClientConfig clientCfg= { - .comm = commClientCfg, -}; - -/* Step 4: Allocate the client context */ -whClientContext clientCtx = {0}; - -/* Step 5: Initialize the client with the provided configuration */ -wh_Client_Init(&clientCtx, &clientCfg); - -/* Step 6: Use the client APIs to interact with the server */ - -/* Buffers to hold sent and received data */ -char recvBuffer[WH_COMM_DATA_LEN] = {0}; -char sendBuffer[WH_COMM_DATA_LEN] = {0}; - -uint16_t sendLen = snprintf(&sendBuffer, - sizeof(sendBuffer), - "Hello World!\n"); -uint16_t recvLen = 0; - -/* Send an echo request and block on receiving a response */ -wh_Client_Echo(client, sendLen, &sendBuffer, &recvLen, &recvBuffer); - -if ((recvLen != sendLen ) || - (0 != memcmp(sendBuffer, recvBuffer, sendLen))) { - /* Error, we weren't echoed back what we sent */ -} -``` - -For more information, refer to [Chapter 5: Client Library](./chapter05.md). - -## Basic Server Configuration - -*Note: A wolfHSM port comes with a reference server application that is already configured to run on the HSM core and so manual server configuration is not required.* - -Configuring a wolfHSM server involves allocating a server context structure and initializing it with a valid client configuration that enables it to perform the requested operations. These operations usually include client communication, cryptographic operations, managing keys, and non-volatile object storage. Depending on the required functionality, not all of these configuration components need to be initialized. - - -The steps required to configure a server that supports client communication, NVM object storage using the NVM flash configuration, and local crypto (software only) are: - -1. Initialize the server comms configuration - 1\. Allocate and initialize a transport configuration structure, context, and callback implementation for the desired transport - 2\. Allocate and initialize a comm server configuration structure using the transport configuration from step 1.1 -2. Initialize the server NVM context - 1\. Allocate and initialize a config, context, and callback structure for the low-level flash storage drivers (the implementation of these structures is provided by the port) - 2\. Allocate and initialize an NVM flash config, context, and callback strucure and bind the port flash configuration from step 2.1 to them - 3\. Allocate an NVM context structure and initialize it with the configuration from step 2.2 using `wh_Nvm_Init()` -3. Allocate and initialize a crypto context structure for the server -4. Initialize wolfCrypt (before initializing the server) -5. Allocate and initialize a server config structure and bind the comm server configuration, NVM context, and crypto context to it -6. Allocate a server context structure and initialize it with the server configuration using `wh_Server_Init()` -7. Set the server connection state to connected using `wh_Server_SetConnected()` when the underlying transport is ready to be used for client communication (see [wolfHSM Examples](https://github.com/wolfSSL/wolfHSM/tree/main/examples) for more information) -8. Process client requests using `wh_Server_HandleRequestMessage()` - -The server may be configured to support NVM object storage using NVM flash configuration. Include the steps to [initialize NVM](./chapter04.md#NVM-Architecture) on the server after step 1. - -```c -#include /* for memcmp() */ -#include "wolfhsm/server.h" /* Server API (includes comm config) */ -#include "wolfhsm/wh_transport_mem.h" /* transport implementation */ - -/* Step 1.1: Allocate and initialize the shared memory transport configuration */ -/* Shared memory transport configuration */ -static whTransportMemConfig transportMemCfg = { /* shared memory config */ }; - -/* Shared memory transport context (state) */ -whTransportMemServerContext transportMemServerCtx = {0}; - -/* Callback structure that binds the abstract comm transport interface to - * our concrete implementation */ -whTransportServerCb transportMemServerCb = {WH_TRANSPORT_MEM_SERVER_CB}; - -/* Step 1.2: Allocate a comm server configuration structure and bind to the - * transport */ -/* Configure the server comms to use the selected transport configuration*/ -whCommServerConfig commServerCfg = { - .transport_cb = transportMemServerCb, - .transport_context = (void*)transportMemServerCtx, - .transport_config = (void*)transportMemCfg, - .server_id = 456, /* unique server identifier */ -}; - -/* Initialize the server NVM context */ - -/* Step 2.1: Allocate and initialize context and config for port-specific - * flash storage drivers */ - -/* Port Flash context (structure names are port-specific) */ -MyPortFlashContext portFlashCtx = {0} - -/* Port Flash config */ -MyPortFlashConfig portFlashCfg = { /* port specific configuration */ }; - -/* NVM Flash callback implementation for Port Flash */ -whFlashCb portFlashCb = { /* port flash implementation of NVM Flash callbacks */ - -/* Step 2.2: Allocate and initialize NVM flash config structure and bind to port - * configuration from step 2.1 */ -whNvmFlashConfig nvmFlashCfg = { - .cb = portFlashCb, - .context = portFlashCtx, - .config = portFlashCfg, -}; -whNvmFlashContext nfc = {0}; - -/* Step 2.3: Allocate NVM context, config, and callback structure and initialize - * with NVM flash configuration from step 2.2 */ -whNvmCb nvmFlashCb = {WH_NVM_FLASH_CB}; - -whNvmConfig nvmConf = { - .cb = nvmFlashCb; - .context = nfc; - .config = nvmFlashCfg, -}; -whNvmContext nvmCtx = {0}; - -wh_Nvm_Init(&nvmCtx, &whNvmConfig); - -/* Step 3: Allocate and initialize a crypto context structure */ -whServerCryptoContext cryptoCtx { - .devID = INVALID_DEVID; /* or set to custom crypto callback devID */ -}; - -/* Allocate and initialize the Server configuration*/ -whServerConfig serverCfg = { - .comm = commServerCfg, - .nvm = nvmCtx, - .crypto = cryptoCtx, -}; - -/* Step 4: Initialize wolfCrypt*/ -wolfCrypt_Init(); - -/* Step 5: Allocate and initialize server config structure and bind the comm - * server configuration and crypto context to it*/ -whServerContext server = {0}; -wh_Server_Init(&server, &serverCfg); - -/* Set server connection state to connected when transport is ready (e.g. - * shared memory buffers cleared) */ -wh_Server_SetConnected(&server, WH_COMM_CONNECTED); - -/* Process client requests*/ -while (1) { - wh_Server_HandleRequestMessage(&server); -} -``` - diff --git a/wolfHSM/src/chapter04.md b/wolfHSM/src/chapter04.md deleted file mode 100644 index 3792aca8..00000000 --- a/wolfHSM/src/chapter04.md +++ /dev/null @@ -1,274 +0,0 @@ -# Library Design / wolfHSM Internals - -wolfHSM is a modular and extensible library designed to provide a secure and efficient hardware security module (HSM) API for embedded systems. The library is built around a set of functional components that can be easily configured and combined to meet the specific requirements of a given application. This chapter provides an overview of the key functional components of wolfHSM, including the component architecture, communications layer, non-volatile memory (NVM), key management, cryptographic operations, and hardware security module (HSM) support. - -## Table of Contents: - -- [Generic Component Architecture](#generic-component-architecture) -- [Communications](#communications) - - [Key Components](#key-components) - - [Client/Server APIs](#clientserver-apis) - - [Comms Layer](#comms-layer) -- [Non Volatile Memory](#non-volatile-memory) - - [NVM Metadata](#nvm-metadata) - - [NVM Architecture](#nvm-architecture) - - [NVM Back-Ends](#nvm-back-ends) -- [Key Management](#key-management) -- [Cryptographic Operations](#cryptographic-operations) - - [Hardware Cryptography Support](#hardware-cryptography-support) - - -## Generic Component Architecture - -To support easily porting wolfHSM to different hardware platforms and build -environments, each component of wolfHSM is designed to have a common initialization, -configuration, and context storage architecture to allow compile-time, link- -time, and/or run-time selection of functional components. Hardware specifics -are abstracted from the logical operations by associating callback functions -with untyped context structures, referenced as a `void*`. - -### Example component initialization - -The prototypical compile-time static instance configuration and initialization -sequence of a wolfHSM component is: - -```c -#include "wolfhsm/component.h" /* wolfHSM abstract API reference for a component */ -#include "port/vendor/mycomponent.h" /* Platform specific definitions of configuration - * and context structures, as well as declarations of - * callback functions */ - -/* Provide the lookup table for function callbacks for mycomponent. Note the type -is the abstract type provided in wolfhsm/component.h */ -whComponentCb my_cb[1] = {MY_COMPONENT_CB}; - -/* Fixed configuration data. Note that pertinent data is copied out of the structure - * during init() */ -const myComponentConfig my_config = { - .my_number = 3, - .my_string = "This is a string", -} - -/* Static allocation of the dynamic state of the myComponent. */ -myComponentContext my_context[1] = {0}; - -/* Initialization of the component using platform-specific callbacks */ -const whComponentConfig comp_config[1] = { - .cb = my_cb, - .context = my_context, - .config = my_config - }; -whComponentContext comp_context[1] = {0}; -int rc = wh_Component_Init(comp_context, comp_config); - -rc = wh_Component_DoSomething(comp_context, 1, 2, 3); -rc = wh_Component_CleanUp(comp_context); -``` - -## Communications - -The communication layer of wolfHSM is designed to provide reliable, bidirectional, and packet-based communication between clients and servers. This layer abstracts the underlying transport mechanisms, allowing for flexibility and modularity. A key aspect of wolfHSM communication is split request and response functions for both client and server, enabling synchronous polling of message reception or asynchronous handling based on interrupt/event support. - -### Key Components - -- Client/Server APIs: Main interface for communicating between client and server. These are the APIs that are directly used by user applications. -- Comms layer: Defines the format and structure of messages exchanged between clients and servers, and provides an abstract interface to the underlying transport layer implementation, exposing a consistent interface for sending and receiving messages. -- Transport Layer: Concrete implementations of the underlying transport. Defines how data is actually transported between client and server. - -### Client/Server APIs - -High-level client and server APIs (defined in `wolfhsm/wh_client.h` and `wolfhsm/wh_server.h`) are the primary interface for communication. These functions abstract the low level communications details from the caller, providing a simple split transaction interface for logical operations. - -For example, using the client API to send an echo request to the server: - -```c -/* send the echo request */ -wh_Client_EchoRequest(&clientCtx, sendLen, &sendBuffer)); - -/* optionally do stuff */ - -/* poll for the server response */ -while (WH_ERROR_NOTREADY == wh_Client_EchoResponse(client, &recv_len, recv_buffer)); -``` - -### Comms Layer - -The comms layer encapsulates the messaging structure and control logic to send and receive data from lower level transports. The comms layer is directly invoked by the higher level client and server APIs. The comms layer provides comm client and comm server abstractions that hold communication state and provide the abstract interface functions to interact with lower level transports. The comms layer API consists of send and receive functions for requests and responses, where the requests and responses pertain to messages rather than high level operations. - -Each client is only allowed a single outstanding request to the server at a time. -The server will process a single request at a time to ensure client isolation. - -#### Messages - -Messages comprise a header with a variable length payload. The header indicates -the sequence id, and type of a request or response. The header also provides -additional fields to provide auxiliary flags or session information. - -```c -/* wolfhsm/wh_comm.h */ - -typedef struct { - uint16_t magic; - uint16_t kind; - uint16_t seq; - uint16_t size; -} whCommHeader; -``` - -Messages are used to encapsulate the request data necessary for the server to -execute the desired function and for the response to provide the results of the -function execution back to the client. Message types are grouped based on the -component that is performing the function and uniquely identify which of the -enumerated functions is being performed. To ensure compatibility (endianness -and version), messages include a Magic field which has known values used to -indicate what operations are necessary to demarshall data passed within the -payload for native processing. Each functional component has a "remote" -implementation that converts between native values and the "on-the-wire" message -formats. The servers ensures the response format matches the request format. - -In addition to passing data contents within messages, certain message types also -support passing shared or mapped memory pointers, especially for performance- -critical operations where the server component may be able to directly access -the data in a DMA fashion. To avoid integer pointer size (IPS) and `size_t` -differences, all pointers and sizes should be sent as `uint64_t` when -possible. - -Messages are encoded in the "on-the-wire" format using the Magic field of the -header indicating the specified endianness of structure members as well as the -version of the communications header (currently 0x01). Server components that -process request messages translate the provided values into native format, -perform the task, and then reencode the result into the format of the request. -Client response handling is not required to process messages that do not match -the request format. Encoded messages assume the same size and layout as the -native structure, with the endianness specified by the Magic field. - -Here is an example of how the client comm layer sends a request: - -```c -uint16_t req_magic = wh_COMM_MAGIC_NATIVE; -uint16_t req_type = 123; -uint16_t request_id; -char* req_data = "RequestData"; -rc = wh_CommClient_SendRequest(context, req_magic, req_type, &request_id, - sizeof(req_data), req_data); -/* Do other work */ - -uint16_t resp_magic, resp_type, resp_id, resp_size; -char response_data[20]; -while((rc = wh_CommClient_RecvResponse(context,&resp_magic, &resp_type, &resp_id, - &resp_size, resp_data)) == WH_ERROR_NOTREADY) { - /* Do other work or yield */ -} -``` - -Note that transport errors passed into the message layer are expected to be fatal and the -client/server should Cleanup any context as a result. - -### Transports - -Transports provide intact packets (byte sequences) of variable size (up to a -maximum MTU), to the messaging layer for the library to process as a request or -response. Transports implement the abstract interface defined by `whTransportClientCb` -and are invoked directly by the commClient/commServer when needing to send and -receive data. - -Custom transport modules that implement the `whTransportClientCb` interface -can be registered with the server and client and then are automatically used -via the standard server and client request/response functions. - -Examples of a memory buffer transport module and a POSIX TCP socket transport can be found in wolfHSM's supported transports. - -#### Supported Transports - -wolfHSM ships with two built-in transports: a memory buffer transport (`wh_transport_mem.c`) and a POSIX TCP socket transport (`port/posix_transport_tcp.c`). - -The memory transport is the default transport for most embedded wolfHSM ports, and is part of the core wolfHSM library. It provides a concrete implementation of the transport callbacks using shared memory blocks between client and server. The shared memory transport mechanism works by allocating two blocks of memory, one for incoming requests and one for outgoing responses. The client writes requests to the incoming memory block and reads responses from the outgoing memory block. The server reads requests from the incoming memory block and writes responses to the outgoing memory block. Each block contains control and status flags signaling to the consumer when it is ready for use. This mechanism is designed to be fast and efficient, as it avoids the need for system calls or network communication. - - -The POSIX TCP transport is part of the wolfHSM POSIX port. It uses TCP sockets as the transport medium for data between client and server. The sockets are IPv4 only and non-blocking. - -## Non Volatile Memory - -Non-Volatile Memory (NVM) in the context of wolfHSM is used to manage persistent objects with metadata and data blocks. The NVM library ensures reliable, atomic operations to ensure transactions are fully committed before returning success. Key operations include adding, listing, reading, and destroying objects, as well as obtaining associated metadata. - -High level NVM features include: - -- API’s to associate metadata (ID, Label, Length, Access, Flags) with variable-sized data within accessible NVM -- Always recoverable using 2 erasable partitions with status flags -- Objects are added by using the next entry and programmed into free space -- Duplicated id’s are allowed but only the latest is readable -- Objects are destroyed by copying the entire space to the inactive partition without the listed objects -- Internal epoch counters used to identify the later objects during recovery - - -### NVM Metadata - -In the wolfHSM library, Non-Volatile Memory (NVM) metadata is used to manage and describe objects stored in NVM. This metadata provides essential information about each object, such as its identifier, access permissions, flags, and other attributes. The metadata ensures that objects can be reliably managed, accessed, and manipulated within the NVM. - -``` -/* User-specified metadata for an NVM object */ -typedef struct { - whNvmId id; /* Unique identifier */ - whNvmAccess access; /* Access Permissions */ - whNvmFlags flags; /* Additional flags */ - whNvmSize len; /* Length of data in bytes */ - uint8_t label[WOLFHSM_NVM_LABEL_LEN]; -} whNvmMetadata; -``` - -- ID (`whNvmId id`): A unique identifier for the NVM object. This ID is used to reference and access the specific object within the NVM. It allows for operations like reading, writing, and deleting the object. -- Access (`whNvmAccess access`): Defines the access permissions for the object. This field specifies who can access the object and under what conditions. It helps enforce security policies and ensures that only authorized entities can interact with the object. -- Flags (`whNvmFlags flags`): Additional flags that provide extra information or modify the behavior of the object. Flags can be used to mark objects with special attributes or states, such as whether the object is read-only, temporary, or has other specific properties. -Length (whNvmSize len): The length of the data associated with the object, in bytes. -- Label (`uint8_t label[]`): A human-readable label or name for the object. - -### NVM Architecture - -The wolfHSM server follows the generic component architecture approach to handle Non-Volatile Memory (NVM) operations. The configuration is divided into generic and specific parts, allowing for flexibility and customization. - -1. **Generic Configuration (wh_nvm.h):** This header file defines the generic interface for NVM operations. It includes function pointers for NVM operations like `nvm_Read`, `nvm_Write`, `nvm_Erase`, and `nvm_Init`. These function pointers are part of the `whNvmConfig` structure, which is used to bind an actual NVM implementation to the abstract NVM interface. - -2. **Specific Configuration (wh_nvm_flash.c, wh_nvm_flash.h):** These files provide a specific implementation of the NVM interface for flash memory. The functions defined here adhere to the function signatures defined in the generic interface, allowing them to be used as the actual implementation for the NVM operations. - -The `whServerContext` structure includes a `whNvmConfig` member. This is used to bind the NVM operations to the server context, allowing the server to perform NVM operations using the configured NVM interface. - -Steps required to initialize NVM on the server are: - -1. Allocate and initialize a `whNvmConfig` structure, providing bindings to a specific NVM back-end (e.g., from `wh_nvm_flash.c`). -2. Allocate and initialize a `whServerConfig` structure, and set its `nvmConfig` member to the `whNvmConfig` structure initialized in step 1. -3. Allocate a `whServerContext` structure. -4. Initialize the server with the `whServerConfig` structure by calling `wh_Server_Init()`. - -This allows the server to use the configured NVM operations on the given backing store, which can be easily swapped out by providing a different implementation in the `whNvmConfig` structure. - -### NVM Back-Ends - -Currently, wolfHSM only supports one NVM back-end provider: the NVM flash module (`wh_nvm_flash.c`). This module provides a concrete implementation of the NMV interface functions (`wh_nvm.h`), mapping the NVM data store to a flash memory device. The low-level flash drivers are device-specific and themselves specified as generic components (`wh_flash.h`) that can be swapped out depending on the target hardware. - -## Key Management - -The wolfHSM library provides comprehensive key management capabilities, including storing, loading, and exporting keys from non-volatile memory, caching of frequently used keys in RAM for fast access, and interacting with hardware-exclusive device keys. Keys are stored in non-volatile memory along side other NVM objects with corresponding access protections. wolfHSM will automatically load keys into the necessary cryptographic hardware when the key is selected for use with a specific consumer. More information on the key management API can be found in the [client library](./chapter05.md) and [API documentation](./appendix01.md) sections. - -## Cryptographic Operations - -One of the defining features of wolfHSM is that it enables the client application to use the wolfCrypt API directly, but with the underlying cryptographic operations actually being executed on the HSM core. This is an incredibly powerful feature for a number of reasons: - -- client applications are dramatically simpler as they do not need to set up the complicated communication transactions required to pass data back and forth between the HSM -- local and remote HSM implementations can be easily switched between by changing a single parameter to the wolfCrypt call, enabling maximum flexibility of implementation and ease of development. Client application development can be prototyped with local instances of wolfCrypt before the HSM core is even brought on-line -- the wolfHSM API is simple, stable, well documented, and battle tested - -The ability to easily redirect wolfCrypt API calls to the wolfHSM server is based on the "crypto callback" (a.k.a cryptocb) of wolfCrypt. - - -The wolfHSM client is able to redirect wolfCrypt API calls to the wolfHSM server by implementing the remote procedure call logic as a [crypto callback](https://www.wolfssl.com/documentation/manuals/wolfssl/chapter06.html#crypto-callbacks-cryptocb). The Crypto callback framework in wolfCrypt enables users to override the default implementation of select cryptographic algorithms and provide their own custom implementations at runtime. The wolfHSM client library registers a crypto callback with wolfCrypt that transforms each wolfCrypt crypto API function into a remote procedure call to the HSM server to be executed in a secure environment. Crypto callbacks are selected for use based on the device ID (`devId`) parameter accepted by most wolfCrypt API calls. - -wolfHSM defines the `WOLFHSM_DEV_ID` value to represent the wolfHSM server crypto device, which can be passed to any wolfCrypt function as the `devId` parameter. wolfCrypt APIs that support the `devId` parameter can be passed `WOLFHSM_DEV_ID` and, if supported, the cryptographic operation will be automatically exectued by the wolfHSM server. - -### Hardware Cryptography Support - -Many HSM devices also have hardware acceleration capabilities for select algorithms available. In these cases, the wolfHSM server may also support offloading the HSM server-side cryptography to device hardware. If supported, the wolfHSM server can be configured to do this automatically with no input required from the user. Any port-specific hardware acceleration capabilities will be documented in the wolfHSM port for that device. - - -## AUTOSAR SHE - -TODO diff --git a/wolfHSM/src/chapter05.md b/wolfHSM/src/chapter05.md deleted file mode 100644 index dab16951..00000000 --- a/wolfHSM/src/chapter05.md +++ /dev/null @@ -1,370 +0,0 @@ -# wolfHSM Client Library - -The client library API is the primary mechanism through which users will interact with wolfHSM. Refer to the [API documentation](appendix01.md) for a full list of available functions and their descriptions. - -## Table of Contents - -- [API Return Codes](#api-return-codes) -- [Split Transaction Processing](#split-transaction-processing) -- [The Client Context](#the-client-context) - - [Initializing the client context](#initializing-the-client-context) -- [NVM Operations](#nvm-operations) -- [Key Management](#key-management) -- [Cryptography](#cryptography) -- [AUTOSAR SHE API](#autosar-she-api) - - -## API Return Codes - -All client API functions return a wolfHSM error code indicating success or the type of failure. Some failures are critical errors, while others may simply indicate an action is required from the caller (e.g. `WH_ERROR_NOTREADY` in the case of a non-blocking operation). Many client APIs also propagate a server error code (and in some cases an additional status) to the caller, allowing for the case where the underlying request transaction succeeded but the server was unable to perform the operation. Examples of this include requesting an NVM object from the server that doesn't exist, attempting to add an object when NVM is full, or trying to use a cryptographic algorithm that the server is not configured to support. - -Error codes are defined in `wolfhsm/wh_error.h`. Refer to the API documentation for more details. - -## Split Transaction Processing - -Most client APIs are fully asynchronous and decomposed into split transactions, meaning there is a separate function for the operation request and response. The request function sends the request to the server and immediately returns without blocking. The response function polls the underlying transport for a response, processing it if it exists, and immediately returning if it has not yet arrived. This allows for the client to request long running operations from the server without wasting client CPU cycles. The following example shows an example asynchronous request and response invocation using the "echo" message: - -```c -int rc; - -/* send an echo request */ -rc = wh_Client_EchoRequest(&clientCtx, sendLen, &sendBuffer); -if (rc != WH_ERROR_OK) { - /* handle error */ -} - -/* do work... */ - -/* poll for a server response */ -while ((rc = wh_Client_EchoResponse(client, &recv_len, recv_buffer)) == WH_ERROR_NOTREADY) { - /* do work or yield */ -} - -if (rc != WH_ERROR_OK) { - /* handle error */ -} - - -``` - -## The Client Context - -The client context structure (`whClientContext`) holds the runtime state of the client and represents the endpoint of the connection with the server. There is a one-to-one relationship between client and server contexts, meaning an application that interacts with multiple servers will need multiple client contexts - one for each server. Each client API function takes a client context as an argument, indicating which server connection the operations will correspond to. If familiar with wolfSSL, the client context structure is analogous to the `WOLFSSL` connection context structure. - -### Initializing the client context - -Before using any client APIs on a client context, the structure must be configured and initialized using the `whClientConfig` configuration structure and the `wh_Client_Init()` function. - -The client configuration structure holds the communication layer configuration (`whCommClientConfig`) that will be used to configure and initialize the context for the server communication. The `whCommClientConfig` structure binds an actual transport implementation (either built-in or custom) to the abstract comms interface for the client to use. - -The general steps to configure a client are: - -1. Allocate and initialize a transport configuration structure, context, and callback implementation for the desired transport -2. Allocate and comm client configuration structure and bind it to the transport configuration from step 1 so it can be used by the client -3. Allocate and initialize a client configuration structure using the comm client configuration in step 2 -4. Allocate a client context structure -5. Initialize the client with the client configuration by calling `wh_Client_Init()` -6. Use the client APIs to interact with the server - -Here is a bare-minimum example of configuring a client application to use the built-in shared memory transport: - -```c -#include /* for memcmp() */ -#include "wolfhsm/client.h" /* Client API (includes comm config) */ -#include "wolfhsm/wh_transport_mem.h" /* transport implementation */ - -/* Step 1: Allocate and initialize the shared memory transport configuration */ -/* Shared memory transport configuration */ -static whTransportMemConfig transportMemCfg = { /* shared memory config */ }; -/* Shared memory transport context (state) */ -whTransportMemClientContext transportMemClientCtx = {0}; -/* Callback structure that binds the abstract comm transport interface to - * our concrete implementation */ -whTransportClientCb transportMemClientCb = {WH_TRANSPORT_MEM_CLIENT_CB}; - -/* Step 2: Allocate client comm configuration and bind to the transport */ -/* Configure the client comms to use the selected transport configuration */ -whCommClientConfig commClientCfg[1] = {{ - .transport_cb = transportMemClientCb, - .transport_context = (void*)transportMemClientCtx, - .transport_config = (void*)transportMemCfg, - .client_id = 123, /* unique client identifier */ -}}; - -/* Step 3: Allocate and initialize the client configuration */ -whClientConfig clientCfg= { - .comm = commClientCfg, -}; - -/* Step 4: Allocate the client context */ -whClientContext clientCtx = {0}; - -/* Step 5: Initialize the client with the provided configuration */ -wh_Client_Init(&clientCtx, &clientCfg); -``` - -The client context is now initialized and can be used with the client library API functions in order to do work. Here is an example of sending an echo request to the server: - -```c -/* Step 6: Use the client APIs to interact with the server */ - -/* Buffers to hold sent and received data */ -char recvBuffer[WH_COMM_DATA_LEN] = {0}; -char sendBuffer[WH_COMM_DATA_LEN] = {0}; - -uint16_t sendLen = snprintf(&sendBuffer, - sizeof(sendBuffer), - "Hello World!\n"); -uint16_t recvLen = 0; - -/* Send an echo request and block on receiving a response */ -wh_Client_Echo(client, sendLen, &sendBuffer, &recvLen, &recvBuffer); - -if ((recvLen != sendLen ) || - (0 != memcmp(sendBuffer, recvBuffer, sendLen))) { - /* Error, we weren't echoed back what we sent */ -} -``` - -While there are indeed a large number of nested configurations and structures to set up, designing wolfHSM this way allowed for different transport implementations to be swapped in and out easily without changing the client code. For example, in order to switch from the shared memory transport to a TCP transport, only the transport configuration and callback structures need to be changed, and the rest of the client code remains the same (everything after step 2 in the sequence above). - -```c -#include /* for memcmp() */ -#include "wolfhsm/client.h" /* Client API (includes comm config) */ -#include "port/posix_transport_tcp.h" /* transport implementation */ - -/* Step 1: Allocate and initialize the posix TCP transport configuration */ -/* Client configuration/contexts */ -whTransportClientCb posixTransportTcpCb = {PTT_CLIENT_CB}; -posixTransportTcpClientContext posixTranportTcpCtx = {0}; -posixTransportTcpConfig posixTransportTcpCfg = { - /* IP and port configuration */ -}; - -/* Step 2: Allocate client comm configuration and bind to the transport */ -/* Configure the client comms to use the selected transport configuration */ -whCommClientConfig commClientCfg = {{ - .transport_cb = posixTransportTcpCb, - .transport_context = (void*)posixTransportTcpCtx, - .transport_config = (void*)posixTransportTcpCfg, - .client_id = 123, /* unique client identifier */ -}}; - -/* Subsequent steps remain the same... */ -``` - -Note that the echo request in step 6 is just a simple usage example. Once the connection to the server is set up, any of the client APIs are available for use. - -## NVM Operations - -This section provides examples of how to use the client NVM API. Blocking APIs are used for simplicity, though the split transaction APIs can be used in a similar manner. - -Client usage of the server NVM storage first requires sending an initialization request to the server. This currently does not trigger any action on the server side but it may in the future and so it is recommended to include in client applications. - -```c -int rc; -int serverRc; -uint32_t clientId; /* unused for now */ -uint32_t serverId; - -rc = wh_Client_NvmInit(&clientCtx, &serverRc, &clientId, &serverId); - -/* error check both local and remote error codes */ -/* serverId holds unique ID of server */ -``` - -Once initialized, the client can create and add an object using the `NvmAddObject` functions. Note that a metadata entry must be created for every object. - -```c -int serverRc; - -whNvmId id = 123; -whNvmAccess access = WOLFHSM_NVM_ACCESS_ANY; -whNvmFlags flags = WOLFHSM_NVM_FLAGS_ANY; -uint8_t label[] = “My Label”; - -uint8_t myData[] = “This is my data.” - -whClient_NvmAddObject(&clientCtx, id, access, flags, strlen(label), &label, sizeof(myData), &myData, &serverRc); -``` - -Data corresponding to an existing objects can be updated in place: - -```c -byte myUpdate[] = “This is my update.” - -whClient_NvmAddObject(&clientCtx, &myMeta, sizeof(myUpdate), myUpdate); -``` - -For objects that should not be copied and sent over the transport, there exist DMA versions of the `NvmAddObject` functions. These pass the data to the server by reference rather than by value, allowing the server to access the data in memory directly. Note that if your platform requires custom address translation or cache invalidation before the server may access client addresses, you will need to implement a [DMA callback](./chapter07#DMA-Callbacks). - -``` -whNvmMetadata myMeta = { - .id = 123, - .access = WOLFHSM_NVM_ACCESS_ANY, - .flags = WOLFHSM_NVM_FLAGS_ANY, - .label = “My Label” -}; - - -uint8_t myData[] = “This is my data.” - -wh_Client_NvmAddObjectDma(client, &myMeta, sizeof(myData), &myData), &serverRc); -``` - -NVM Object data can be read using the `NvmRead` functions. There also exist DMA versions of `NvmRead` functions that can be used identically to their `AddbjectDma` counterparts. - -```c -const whNvmId myId = 123; /* ID of the object we want to read */ -const whNvmSize offset = 0; /* byte offset into the object data */ - -whNvmSize outLen; /* will hold length in bytes of the requested data */ -int outRc; /* will hold server return code */ - -byte myBuffer[BIG_SIZE]; - -whClient_NvmRead(&clientCtx, myId, offset, sizeof(myData), &serverRc, outLen, &myBuffer) -/* or via DMA */ -whClient_NvmReadDma(&clientCtx -iint wh_Client_NvmReadDma(&clientCtx, myid, offset, sizeof(myData), &myBuffer, &serverRc); -``` - -Objects can be deleted/destroyed using the `NvmDestroy` functions. These functions take a list (array) of object IDs to be deleted. IDs in the list that are not present in NVM do not cause an error. - -```c -whNvmId idList[] = {123, 456}; -whNvmSize count = sizeof(myIds)/ sizeof(myIds[0]); -int serverRc; - -wh_Client_NvmDestroyObjectsRequest(&clientCtx, count, &idList); -wh_Client_NvmDestroyObjectsResponse(&clientCtx, &serverRc); -``` - -The objects in NVM can also be enumerated using the `NvmList` functions. These functions retrieve the next matching id in the NVM list starting at `start_id`, and sets `out_count` to the total number of IDs that match `access` and `flags`: - -```c -int wh_Client_NvmList(whClientContext* c, - whNvmAccess access, whNvmFlags flags, whNvmId start_id, - int32_t *out_rc, whNvmId *out_count, whNvmId *out_id); -``` - -For a full description of all the NVM API functions, please refer to the [API documentation](./appendix01.md). - -## Key Management - -Keys meant for use with wolfCrypt can be loaded into the HSM's keystore and optionally saved to NVM with the following APIs: - -```c -#include "wolfhsm/wh_client.h" - -uint16_t keyId = WOLFHSM_KEYID_ERASED; -uint32_t keyLen; -byte key[AES_128_KEY_SIZE] = { /* AES key */ }; -byte label[WOLFHSM_NVM_LABEL_LEN] = { /* Key label */ }; - -whClientContext clientCtx; -whClientCfg clientCfg = { /* config */ }; - -wh_Client_Init(&clientCtx, &clientCfg); - -wh_Client_KeyCache(clientCtx, 0, label, sizeof(label), key, sizeof(key), &keyId); -wh_Client_KeyCommit(clientCtx, keyId); -wh_Client_KeyEvict(clientCtx, keyId); -keyLen = sizeof(key); -wh_Client_KeyExport(clientCtx, keyId, label, sizeof(label), key, &keyLen); -wh_Client_KeyErase(clientCtx, keyId); -``` - -`wh_Client_KeyCache` will store the key and label in the HSM's ram cache and correlate it with the `keyId` passed in. Using a `keyId` of `WOLFHSM_KEYID_ERASED` will make wolfHSM assign a new, unique `keyId` that will be returned through the keyId parameter. wolfHSM has a limited number of cache slots, configured by `WOLFHSM_NUM_RAMKEYS`, and will return `WH_ERROR_NOSPACE` if all keyslots are full. Keys that are in cache and NVM will be removed from the cache to make room for more keys since they're backed up in NVM. -`wh_Client_KeyCommit` will save a cached key to NVM with the key indicated by it's keyId. -`wh_Client_KeyEvict` will evict a key from the cache but will leave it in NVM if it's been commited. -`wh_Client_KeyExport` will read the key contents out of the HSM back to the client. -`wh_Client_KeyErase` will remove the indicated key from cache and erase it from NVM. - -## Cryptography - -When using wolfCrypt in the client application, compatible crypto operations can be executed on the wolfHSM server by passing `WOLFHSM_DEV_ID` as the `devId` argument. The wolfHSM client must be initialized before using any wolfHSM remote crypto. - -If wolfHSM does not yet support that algorithm, the API call will return `CRYPTOCB_UNAVAILABLE`. - -Here is an example of how a client application would perform an `AES CBC` encryption operation on the wolfHSM server: - -```c -#include "wolfhsm/client.h" -#include "wolfssl/wolfcrypt/aes.h" - -whClientContext clientCtx; -whClientCfg clientCfg = { /* config */ }; - -wh_Client_Init(&clientCtx, &clientCfg); - -Aes aes; -byte key[AES_128_KEY_SIZE] = { /* AES key */ }; -byte iv[AES_BLOCK_SIZE] = { /* AES IV */ }; - -byte plainText[AES_BLOCK_SIZE] = { /* plaintext */ }; -byte cipherText[AES_BLOCK_SIZE]; - -wc_AesInit(&aes, NULL, WOLFHSM_DEV_ID); - -wc_AesSetKey(&aes, &key, AES_BLOCK_SIZE, &iv, AES_ENCRYPTION); - -wc_AesCbcEncrypt(&aes, &cipherText, &plainText, sizeof(plainText)); - -wc_AesFree(&aes); -``` - -If it is necessary to use an HSM-owned key instead of a client-owned key (e.g. a HSM hardware key), client API functions such as `wh_Client_SetKeyAes` (or similar for other crypto algorithms) will make wolfHSM use the indicated HSM key for the subsequent cryptographic operation instead of requiring a client-supplied key: - -```c -#include "wolfhsm/client.h" -#include "wolfssl/wolfcrypt/aes.h" - -whClientContext clientCtx; -whClientCfg clientCfg = { /* config */ }; - -wh_Client_Init(&clientCtx, &clientCfg); - -uint16_t keyId; -Aes aes; -byte key[AES_128_KEY_SIZE] = { /* AES key */ }; -byte label[WOLFHSM_NVM_LABEL_LEN] = { /* Key label */ }; -byte iv[AES_BLOCK_SIZE] = { /* AES IV */ }; - -byte plainText[AES_BLOCK_SIZE] = { /* plaintext */ }; -byte cipherText[AES_BLOCK_SIZE]; - -wc_AesInit(&aes, NULL, WOLFHSM_DEV_ID); - -/* IV needs to be set seperate from the key */ -wc_AesSetIV(&aes, iv); - -/* this key can be cached at any time before use, done here for the sake of example */ -wh_Client_KeyCache(clientCtx, 0, label, sizeof(label), key, sizeof(key), &keyId); - -wh_Client_SetKeyAes(&aes, keyId); - -wc_AesCbcEncrypt(&aes, &cipherText, &plainText, sizeof(plainText)); - -/* key eviction is optional, the key can be stored in cache or NVM and used with wolfCrypt */ -wh_Client_KeyEvict(clientCtx, keyId); - -wc_AesFree(&aes); -``` - -If it is desired to run the crypto locally on the client, all that is necessary is to pass `INVALID_DEVID` to `wc_AesInit()`: - -```c -wc_AesInit(&aes, NULL, INVALID_DEVID); -``` - -Outside of the steps mentioned above, the usage of the wolfHSM API should be otherwise unchanged. Please consult the wolfCrypt API reference inside the [wolfSSL manual](https://www.wolfssl.com/documentation/manuals/wolfssl/index.html) for further usage instructions and the extensive list of supported cryptographic algorithms. - -### CMAC - -For CMAC operations that need to use cached keys, seperate wolfHSM specific functions must be called to do the CMAC hash and verify operation in one function call. The normal `wc_AesCmacGenerate_ex` and `wc_AesCmacVerify_ex` are acceptable to use if the client can supply a key when the functions are invoked, but in order to use a pre-cached key, `wh_Client_AesCmacGenerate` and `wh_Client_AesCmacVerify` must be used. The non-oneshot functions `wc_InitCmac_ex`, `wc_CmacUpdate` and `wc_CmacFinal` can be used with either a client-side key or a pre-cached key. To use a cached key for these functions, the caller should pass a `NULL` key parameter and use `wh_Client_SetKeyCmac` to set the appropriate keyId. - - -## AUTOSAR SHE API - - diff --git a/wolfHSM/src/chapter06.md b/wolfHSM/src/chapter06.md deleted file mode 100644 index 7513d37d..00000000 --- a/wolfHSM/src/chapter06.md +++ /dev/null @@ -1,24 +0,0 @@ -# wolfHSM Server Library - -The wolfHSM server library is a server-side implementation of the wolfCrypt cryptography library. -It provides an interface for applications to offload cryptographic operations to a -dedicated server, which runs the wolfHSM server software. This allows the application to perform -cryptographic operations without having to manage the cryptographic keys or perform the -operations locally. - -## Getting Started -TODO - -## Architecture -TODO - -## API Reference -TODO - -## Key Management -TODO - -## Cryptographic - -wolfHSM uses wolfCrypt for all cryptographic operations, which means wolfHSM can offload any algorithm supported by wolfCypt to run on the wolfHSM server. This includes the Chinese government mandated ShāngMì ciphers (SM2, SM3, SM4), as well as post-quantum algorithms such as Kyber, LMS, XMSS, and more! - diff --git a/wolfHSM/src/chapter07.md b/wolfHSM/src/chapter07.md deleted file mode 100644 index 276e5a3e..00000000 --- a/wolfHSM/src/chapter07.md +++ /dev/null @@ -1,431 +0,0 @@ -# Customizing wolfHSM - -wolfHSM provides multiple points of customization via build time options and user-supplied callbacks, enabling it to to be tailored to a wide range of use cases and environments without requiring changes to the core library code. This chapter provides an overview of the customization options available in wolfHSM, including: - -- [Library Configuration](#library-configuration): Compile-time options that can be used to enable or disable specific features in the library. -- [DMA Callbacks](#dma-callbacks): Custom callbacks that can be registered with the server to perform operations before and after accessing client memory directly. -- [DMA Address Allow List](#dma-address-allow-list): A mechanism for the server to restrict the client's access to specific memory regions. -- [Custom Callbacks](#custom-callbacks): Custom callbacks that can be registered with the server and invoked by the client to perform specific operations that are not covered by the default HSM capabilities. - -## Library Configuration - -The wolfHSM library has a number of build options that can be turned on or off though compile time definitions. The library expects these configuration macros to be defined in a configuration header named `wh_config.h`. This file should be defined by applications using wolfHSM and located in a directory in the compilers include path. - -An example `wh_config.h` is distributed with every wolfHSM port providing a known good configuration. - -For a full list of wolfHSM configuration settings that can be defined in `wh_config.h`, refer to the [API documentation](appendix01.md). - -## DMA Callbacks - -The Direct Memory Access (DMA) callback feature in wolfHSM provides hooks on the server side for custom operations before and after accessing client memory directly. This is often required when porting to a new shared memory architecture. The feature is particularly useful for scenarios where the server needs to perform specific actions such as cache invalidation, address translation, or other custom memory manipulations to ensure coherency between client and server memory. - -Callbacks can be registered with a server using the `wh_Server_DmaRegisterCb32()` and `wh_Server_DmaRegisterCb64()` functions, which bind the supplied callback to all DMA operations on the server context. - -Separate callback functions for handling 32 and 64-bit addresses are required, corresponding to the distinct 32 and 64-bit client DMA API functions. Callback functions are of type `whServerDmaClientMem32Cb` and `whServerDmaClientMem64Cb`, respectively, defined as: - -```c -typedef int (*whServerDmaClientMem32Cb)(struct whServerContext_t* server, - uint32_t clientAddr, void** serverPtr, - uint32_t len, whServerDmaOper oper, - whServerDmaFlags flags); -typedef int (*whServerDmaClientMem64Cb)(struct whServerContext_t* server, - uint64_t clientAddr, void** serverPtr, - uint64_t len, whServerDmaOper oper, - whServerDmaFlags flags); -``` - -The DMA callback functions receive the following arguments: - -- `server`: A pointer to the server context. -- `clientAddr`: The client memory address to be accessed. -- `serverPtr`: A pointer to a the server memory address (also a pointer), which the callback will set after applying any necessary transformations/remappings -- `len`: The length of the requested memory operation in bytes -- `oper`: The type of memory operation (injection point in the next section) that is about to be performed on the transformed server address -- `flags`: Additional flags for the memory operation. Right now these are reserved for future use and should be ignored. - -The callback should return `WH_ERROR_OK` on success, or an error code if an error occurs. The server will propagate the error code back to the client if the callback fails. - -### Callback Locations - -The DMA callbacks are at four distinct points around the server's memory access: - -- Pre-Read: Callback is invoked before reading data from the client memory. The server should use the callback to perform any necessary pre-read operations, such as address translation or cache invalidation. -- Post-Read: Callback is invoked after reading data from the client memory. The server should use the callback to perform any necessary post-read operations, such as cache synchronization. -- Pre-Write: Callback is invoked before writing data to the client memory. The server should use the callback to perform any necessary pre-write operations, such as address translation or cache invalidation. -- Post-write: Callback is invoked after writing data to the client memory. The server should use the callback to perform any necessary post-write operations, such as cache synchronization. - -The point at which the callback is invoked is passed into the callback through the `oper` argument, which can take the following values: - -```c -typedef enum { - WH_SERVER_DMA_OPER_PRE_READ, /* Pre-read operation */ - WH_SERVER_DMA_OPER_POST_READ, /* Post-read operation */ - WH_SERVER_DMA_OPER_PRE_WRITE, /* Pre-write operation */ - WH_SERVER_DMA_OPER_POST_WRITE /* Post-write operation */ -} whServerDmaOper; -``` - -This enables the callback to `switch` on the `oper` value and perform custom logic based on the type of memory operation being performed. An example DMA callback implementation is shown below: - -```c -#include "wolfhsm/wh_server.h" -#include "wolfhsm/wh_error.h" - -/* Example DMA callback for 32-bit client addresses */ -int myDmaCallback32(whServerContext* server, uint32_t clientAddr, - void** xformedCliAddr, uint32_t len, - whServerDmaOper oper, whServerDmaFlags flags) -{ - /* Optionally transform client address to server address space, e.g. memmap() */ - *xformedCliAddr = (void*)clientAddr; /* do transformation */ - - switch (oper) { - case WH_DMA_OPER_CLIENT_READ_PRE: - /* Pre-Read Operation here, e.g. cache invalidation */ - break; - case WH_DMA_OPER_CLIENT_READ_POST: - /* Post-Read Operation here */ - break; - case WH_DMA_OPER_CLIENT_WRITE_PRE: - /* Pre-Write Operation here */ - break; - case WH_DMA_OPER_CLIENT_WRITE_POST: - /* Post-Write Operation here, e.g. cache flush */ - break; - default: - return WH_ERROR_BADARGS; - } - - return WH_ERROR_OK; -} -``` - -### Callback Registration - -The callback can be registered with the server context, either at initialization through the server configuration structure, or at any time after initialization using the callback registration functions. - -To register the callback at initialization, the callback function should be included in the DMA configuration structure within the server configuration structure. Note that the callback functions are optional, so unused callbacks can be set to `NULL`. - -```c -#include "wolfhsm/wh_server.h" - -/* Example of initializing a server config structr with a DMA32 callback then initializing the server */ -int main(void) -{ - whServerDmaConfig dmaCfg = {0}; - dmaCfg.dma32Cb = myDmaCallback32; - - - whServerConfig serverCfg = { - .dmaCfg = dmaCfg, - - /* other configuration omitted for brevity */ - }; - - whServerContext serverCtx; - - wh_Server_Init(&serverCtx, &serverCfg); - - /* server app logic */ -} -``` - -To register the callback after initialization, first initialize the server context with the desired configuration, then call the appropriate registration function. - -```c -#include "wolfhsm/wh_server.h" - -int main(void) -{ - - whServerConfig serverCfg = { /* server config */ }; - - whServerContext serverCtx; - - wh_Server_Init(&serverCtx, &serverCfg); - - /* register the callback defined above */ - wh_Server_DmaRegisterCb32(&serverCtx, myDmaCallback32); - - /* server app logic */ -} -``` - -## DMA Address Allow List - -wolfHSM also exposes an "allow list" for client DMA addresses, providing a mechanism for the server to restrict the client's access to a pre-configured list of specific memory regions. This feature is particularly useful in scenarios where the server needs to limit the client's access to certain memory regions to prevent unauthorized access or to ensure that the client only accesses memory that is safe to access. For example, in a multicore system with one client running per-core, it is most likely that clients should not be able to access each others memory regions, nor read out server memory which could contain sensitive information like cryptographic keys. - -It is important to note that the software allow list feature is meant to work as a second layer of protection on top of device-specific memory protection mechanisms, and should not be considered a first line of defense in preventing unauthorized memory accesses. It is imperative that the user configure the device-specific memory protection mechanisms required to enforce the isolation of their applications and segment the HSM core and associated memory from the rest of the system. - -### Registering an Allow List - -Similar to the DMA callbacks, the allow list can be registered with the server context, either at initialization through the server configuration structure, or at any time after initialization using the allow list registration functions. - -To register the list at initialization, the list should be populated in the DMA configuration structure inside the server configuration structure. - -```c -#include "wolfhsm/wh_server.h" -#include "wolfhsm/wh_error.h" - -/* Define the allowed memory regions */ -const whServerDmaAddrAllowList allowList = { - .readList = { - {(void*)0x20001000, 0x100}, /* Allow read from 0x20001000 to 0x200010FF */ - {(void*)0x20002000, 0x200}, /* Allow read from 0x20002000 to 0x200021FF */ - }, - .writeList = { - {(void*)0x20003000, 0x100}, /* Allow write from 0x20003000 to 0x200030FF */ - {(void*)0x20004000, 0x200}, /* Allow write from 0x20004000 to 0x200041FF */ - }, -}; - -int main() -{ - whServerConfig config; - - - whServerDmaConfig dmaCfg = {0}; - dmaCfg.allowList = &allowList; - - whServerConfig serverCfg = { - .dmaCfg = dmaCfg, - /* other configuration omitted for brevity */ - }; - - whServerContext server; - - wh_Server_Init(&server, &config); - - /* Server is now configured with the allowlist */ - /* Perform other server operations */ - - /* Allow list can also be registered after initialization if the - * list is not present in the server configuration struct using: - * - * wh_Server_DmaRegisterAllowList(&server, &allowList); - */ -} -``` - -Once registered, all DMA operations requested of the server by the client will be checked against the allow list. If the client attempts to access a memory region that is not in the allow list, the server will return an error to the client, and the operation will not be performed. - -## Custom Callbacks - -The custom callback feature in wolfHSM allows developers to extend the functionality of the library by registering custom callback functions on the server. These callbacks can then be invoked by clients to perform specific operations that are not covered by the default HSM capabilities such as enabling or disabling peripheral hardware, implementing custom monitoring or authentication routines, staging secure boot for an additional core, etc. - -### Server side - -The server can register custom callback functions that define specific operations. These functions must be of type `whServerCustomCb`. - -```c -/* wh_server.h */ - -/* Type definition for a custom server callback */ -typedef int (*whServerCustomCb)( - whServerContext* server, /* points to dispatching server ctx */ - const whMessageCustomCb_Request* req, /* request from client to callback */ - whMessageCustomCb_Response* resp /* response from callback to client */ -); - -``` - -Custom server callback functions are associated with unique identifiers (IDs), which correspond to indices into the server's custom callback dispatch table. The client will refer to the callback by it's ID when it requests invocation. - -The custom callback has access to data passed from the client by value or by reference (useful in a shared memory system) through the `whMessageCustomCb_Request` argument passed into the callback function. The callback can act on the input data and produce output data that can be passed back to the client through th e`whMessageCustomCb_Response` argument. The custom callback does not need to handle sending or receiving any of the input / output client data, as this is handled externally by wolfHSM. The response structure also contains fields for an error code and return code to propagate back to the client. The error code should be populated by the callback, and the return code will be set the return value from the custom callback. - -### Client Side - -Clients can send requests to the server to invoke these custom callbacks. The API provides a request and response function similar to the other functions in the client API. The client should declare an instance of a custom request structure, populate it with its custom data, and then send it to the server using `wh_Client_CustomCbRequest()`. The server response can then be polled using `wh_Client_CustomCbResponse()`, and the response data will populate the output `whMessageCustomCb_Response()` on successful receipt. - -The client can also check the registration status of a given callback ID using the `wh_Client_CustomCheckRegistered()` family of functions. This function queries the server for whether a given callback ID is registered in its internal callback table. The server responds with a true or false indicating the registration status. - -### Custom Messaging - -The client is able to pass data in and receive data from the custom callbacks through the custom request and response message data structures. -These custom request and response messages are structured to include a unique ID, a type indicator, and a data payload. The ID corresponds to the index in the server's callback table. The type field indicating to the custom callback how the data payload should be interpreted. -The data payload is a fixed size data buffer that the client can use in any way it wishes. The response structure contains additional error code values described above. - -```c -/* request message to the custom server callback */ -typedef struct { - uint32_t id; /* indentifier of registered callback */ - uint32_t type; /* whMessageCustomCb_Type */ - whMessageCustomCb_Data data; -} whMessageCustomCb_Request; - -/* response message from the custom server callback */ -typedef struct { - uint32_t id; /* indentifier of registered callback */ - uint32_t type; /* whMessageCustomCb_Type */ - int32_t rc; /* Return code from custom callback. Invalid if err != 0 */ - int32_t err; /* wolfHSM-specific error. If err != 0, rc is invalid */ - whMessageCustomCb_Data data; -} whMessageCustomCb_Response; -``` - -### Defining Custom Data Types - -Custom data types can be defined using the `whMessageCustomCb_Data` union, which provides several helpful predefined structures for common data types (e.g., dma32, dma64) and a raw data buffer (buffer) for user-defined schemas. Clients can indicate to the server callback how it should interpret the data in the union through the `type` field in the request. wolfHSM reserves the first few type indices for internal use, with the remainder of the type values available for custom client types. - - -### Custom Callback Example - -In this example, a custom callback is implemented that is able to process three types of client requests, one using the built-in DMA-style addressing type, and two that use custom user defined types. - -First, common messages shared between the client and server should be defined: - -```c -/* my_custom_cb.h */ - -#include "wolfhsm/wh_message_customcb.h" - -#define MY_CUSTOM_CB_ID 0 - -enum { - MY_TYPE_A = WH_MESSAGE_CUSTOM_CB_TYPE_USER_DEFINED_START, - MY_TYPE_B, -} myUserDefinedTypes; - -typedef struct { - int foo; - int bar; -} myCustomCbDataA; - -typedef struct { - int noo; - int baz; -} myCustomCbDataB; -``` - -On the server side, the callback must be defined and then registered with the server context before processing requests. Note that the callback can be registered at any time, not necessarily before processing the first request. - -```c -#include "wolfhsm/wh_server.h" -#include "my_custom_cb.h" - -int doWorkOnClientAddr(uint8_t* addr, uint32_t size) { - /* do work */ -} - -int doWorkWithTypeA(myCustomTypeA* typeA) { - /* do work */ -} - -int doWorkWithTypeB(myCustomTypeB* typeB) { - /* do work */ -} - -static int customServerCb(whServerContext* server, - const whMessageCustomCb_Request* req, - whMessageCustomCb_Response* resp) -{ - int rc; - - resp->err = WH_ERROR_OK; - - /* detect and handle DMA request */ - if (req->type == WH_MESSAGE_CUSTOM_CB_TYPE_DMA32) { - uint8_t* clientPtr = (uint8_t*)((uintptr_t)req->data.dma32.client_addr); - size_t clientSz = req->data.dma32.client_sz; - - if (clientPtr == NULL) { - resp->err = WH_ERROR_BADARGS; - } - else { - rc = doWorkOnClientAddr(clientPtr, clientSz); - } - } - else if (req->type == MY_TYPE_A) { - myCustomCbDataA *data = (myCustomCbDataA*)((uintptr_t)req->data.data); - rc = doWorkWithTypeA(data); - /* optionally set error code of your choice */ - if (/* error condition */) { - resp->err = WH_ERROR_ABORTED; - } - } - else if (req->type == MY_TYPE_B) { - myCustomCbDataB *data = (myCustomCbDataB)((uintptr_t)req->data.data); - rc = doWorkWithTypeB(data); - /* optionally set error code of your choice */ - if (/* error condition */) { - resp->err = WH_ERROR_ABORTED; - } - } - - return rc; -} - - -int main(void) { - - whServerContext serverCtx; - - whServerConfig serverCfg = { - /* your server configuration */ - }; - - wh_Server_Init(&serverCtx, &serverCfg); - - wh_Server_RegisterCustomCb(&serverCtx, MY_CUSTOM_CB_ID, customServerCb)); - - /* process server requests (simplified) */ - while (1) { - wh_Server_HandleRequestMessage(&serverCtx); - } - -} -``` - -Now the client is able to check the registration of the custom callback, as well as invoke it remotely: - -```c -#include "wh_client.h" -#include "my_custom_cb.h" - -whClientContext clientCtx; -whClientConfig clientCfg = { - /* your client configuration */ -}; - -whClient_Init(&clientCtx, &clientCfg); - -bool isRegistered = wh_Client_CustomCheckRegistered(&client, MY_CUSTOM_CB_ID); - -if (isRegistered) { - uint8_t buffer[LARGE_SIZE] = {/* data*/}; - myCustomCbDataA typeA = {/* data */}; - myCustomCbDataB typeB = {/* data */}; - - whMessageCustomCb_Request req = {0}; - whMessageCustomCb_Request resp = {0}; - - /* send custom request with built-in DMA type */ - req.id = MY_CUSTOM_CB_ID; - req.type = WH_MESSAGE_CUSTOM_CB_TYPE_DMA32; - req.data.dma32.client_addr = (uint32_t)((uintptr_t)&data); - req.data.dma32.client_sz = sizeof(data); - wh_Client_CustomCbRequest(clientCtx, &req); - wh_Client_CustomCbResponse(clientCtx, &resp); - /* do stuff with response */ - - /* send custom request with a user defined type */ - memset(req, 0, sizeof(req)); - req.id = MY_CUSTOM_CB_ID; - req.type = MY_TYPE_A; - memcpy(&req.data.data, typeA, sizeof(typeA)); - wh_Client_CustomCbRequest(clientCtx, &req); - wh_Client_CustomCbResponse(clientCtx, &resp); - /* do stuff with response */ - - /* send custom request with a different user defined type */ - memset(req, 0, sizeof(req)); - req.id = MY_CUSTOM_CB_ID; - req.type = MY_TYPE_B; - memcpy(&req.data.data, typeA, sizeof(typeB)); - wh_Client_CustomCbRequest(clientCtx, &req); - wh_Client_CustomCbResponse(clientCtx, &resp); - /* do stuff with response */ -} - -``` - diff --git a/wolfHSM/src/chapter08.md b/wolfHSM/src/chapter08.md deleted file mode 100644 index 095e7b7b..00000000 --- a/wolfHSM/src/chapter08.md +++ /dev/null @@ -1,78 +0,0 @@ -# WolfHSM Porting - -This porting section aims to provide you with wolfHSM porting-related material and information. -We will cover the following: - -- WolfHSM Porting Overview -- WolfHSM Ports -- WolfHSM Porting Interface - -## WolfHSM Porting Overview - -wolfHSM itself is not executable and it does not contain any code to interact with any specific hardware. In order for wolfHSM to run on a specific device, the library must be configured with the necessary hardware drivers and abstraction layers so that the server application can run and communicate with the client. Specifically, getting wolfHSM to run on real hardware requires the implementation of the following: - -- Server application startup and hardware initialization -- Server wolfCrypt configuration -- Server non-volatile memory configuration -- Server and client transport configuration -- Server and client connection handling - -The code that provides these requirements and wraps the server API into a bootable application is collectively referred to as a wolfHSM "port". - -Official ports of wolfHSM are provided for various supported architectures, with each port providing the implementation of the wolfHSM abstractions tailored to the specific device. Each port contains: - -- Standalone Reference Server Application: This application is meant to run on the HSM core and handle all secure operations. It comes fully functional out-of-the-box but can also be customized by the end user to support additional use cases -- Client Library: This library can be linked against user applications to facilitate communication with the server - -## WolfHSM Ports - -### Infineon Aurix TC3XX - -The distribution of this port is restricted by the vendor. Please contact support@wolfssl.com for access. - -**Infineon Aurix TC3xx** - -- Up to 6x 300MHz TriCore application cores -- 1x 100MHz ARM Cortex M3 HSM core -- Crypto offload: TRNG, AES128, ECDSA, ED25519, SHA - -### ST SPC58NN - -The distribution of this port is restricted by the vendor. Please contact support@wolfssl.com for access. - -** ST SPC58NN** - -- 3x 200MHz e200z4256 PowerPC application cores -- 1x 100MHz e200z0 PowerPC HSM core with NVM -- Crypto offload: TRNG, AES128 - -### POSIX - -The POSIX port provides multiple and fully functional implementations of different wolfHSM abstractions that can be used to better understand the exact functionality expected for different hardware abstractions. - -The POSIX port provides: -- Memory buffer transport -- TCP transport -- Unix domain transport -- RAM-based and file-based NVM flash simulators - -### Skeleton - -The Skeleton port source code provides a non-functioning layout to be used as a starting point for future hardware/platform ports. Each function provides the basic description and expected flow with error cases explained so that ports can be used interchangeably with consistent results. - -The Skeleton port provides stub implementations of: -- Transport callbacks -- NVM Flash callbacks -- Crypto callbacks - -## WolfHSM Porting Interface - -Ports must implement hardware-specific interfaces: -- NVM flash interface - -Crypto Hardware -- TRNG, Keys, symmetric/asymmetric crypto - -Platform Interface -- Boot sequence, application core reset, memory limitations -- Port and configuration are selected at compile time diff --git a/wolfHSM/src/wolfHSM-diagram.png b/wolfHSM/src/wolfHSM-diagram.png deleted file mode 100644 index f0db54df..00000000 Binary files a/wolfHSM/src/wolfHSM-diagram.png and /dev/null differ