Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ if(WOLFTPM_FWTPM)
add_executable(fwtpm_unit_test
tests/fwtpm_unit_tests.c
${FWTPM_CORE_SOURCES}
tests/fwtpm_io_test_adapter.c
)
target_compile_definitions(fwtpm_unit_test PRIVATE
"WOLFTPM_FWTPM"
Expand All @@ -594,6 +595,8 @@ if(WOLFTPM_FWTPM)
if(UNIX)
target_link_libraries(fwtpm_unit_test PRIVATE
${WOLFTPM_FWTPM_THREAD_LIBS})
elseif(WIN32)
target_link_libraries(fwtpm_unit_test PRIVATE ws2_32)
endif()

if(WOLFTPM_FWTPM_TIS)
Expand Down
43 changes: 27 additions & 16 deletions docs/fwtpm/hal-and-porting.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
# HAL and Porting

The fwTPM provides hardware abstraction layers (HALs) so it can be ported to embedded targets without modifying the core logic. There is an IO HAL for the transport, an NV HAL for persistent storage, and an optional clock HAL. Full reference ports for several boards live in the [wolftpm-examples](https://github.com/wolfSSL/wolftpm-examples) repository.
The fwTPM provides hardware abstraction layers (HALs) for the server transport, persistent storage, and the platform clock. Full reference ports for several boards live in the [wolftpm-examples](https://github.com/wolfSSL/wolftpm-examples) repository.

## IO HAL (Transport)

The IO HAL abstracts the transport between the fwTPM server and its clients. The default implementation uses TCP sockets (SWTPM protocol). For embedded targets, replace it with SPI, I2C, UART, or shared memory callbacks.
The IO HAL abstracts the transport between the fwTPM server and its clients. Socket builds use TCP sockets (SWTPM protocol) by default. Registering an `FWTPM_IO_HAL` replaces the socket transport with callbacks for an embedded or in-process transport. TIS builds use their separate TIS HAL.

**Callback structure** (defined as `FWTPM_IO_HAL` in `fwtpm.h`):

| Callback | Signature | Description |
|----------|-----------|-------------|
| `send` | `int (*)(void* ctx, const void* buf, int sz)` | Send data to client |
| `recv` | `int (*)(void* ctx, void* buf, int sz)` | Receive data from client |
| `wait` | `int (*)(void* ctx)` | Wait for data or connections. Returns a bitmask: `0x01`=command data, `0x02`=platform data, `0x04`=new command connection, `0x08`=new platform connection |
| `send` | `int (*)(void* ctx, int type, const void* buf, int sz)` | Send data to the command or platform client |
| `recv` | `int (*)(void* ctx, int type, void* buf, int sz)` | Receive data from the command or platform client |
| `wait` | `int (*)(void* ctx, int timeoutMs)` | Wait up to `timeoutMs` for data or connections. Returns 0 on timeout or a bitmask: `0x01`=command data, `0x02`=platform data, `0x04`=new command connection, `0x08`=new platform connection |
| `accept` | `int (*)(void* ctx, int type)` | Accept new connection (type: 0=command, 1=platform) |
| `close_conn` | `void (*)(void* ctx, int type)` | Close connection (type: 0=command, 1=platform) |
| `ctx` | `void*` | User context pointer |

The `type` argument is `FWTPM_IO_TYPE_COMMAND` or `FWTPM_IO_TYPE_PLATFORM`. The `send`, `recv`, and `wait` callbacks are required. `wait` must return by its requested timeout so stop requests are observed; override `FWTPM_IO_WAIT_TIMEOUT_MS` to change the default 1000 ms interval. Connectionless transports may omit `accept` and `close_conn`; a transport that provides `accept` must also provide `close_conn` and clean up any partial connection state before returning an accept error.

**Registration:**

```c
FWTPM_IO_HAL myHal;
XMEMSET(&myHal, 0, sizeof(myHal));
myHal.send = my_send;
myHal.recv = my_recv;
myHal.wait = my_wait;
Expand All @@ -31,6 +34,8 @@ myHal.ctx = &myTransportCtx;
FWTPM_IO_SetHAL(&ctx, &myHal);
Comment thread
dgarske marked this conversation as resolved.
```

Register the IO HAL before `FWTPM_Init()`, or after `FWTPM_Init()` but before `FWTPM_IO_Init()`.

## NV HAL (Persistent Storage)

The NV HAL abstracts persistent storage. The default implementation uses a local file (`fwtpm_nv.bin`). For embedded targets, replace it with flash, EEPROM, or other non-volatile storage callbacks.
Expand Down Expand Up @@ -101,10 +106,12 @@ The clock HAL is optional. It supplies `get_ms()`, which returns milliseconds si

## Porting Example

A bare-metal embedded target with SPI transport and SPI flash NV:
A bare-metal target can register SPI transport and SPI flash NV callbacks before initialization:

```c
FWTPM_CTX ctx;
int cleanupRc;
int rc;
XMEMSET(&ctx, 0, sizeof(ctx));

/* Set custom NV storage before FWTPM_Init, which loads NV state through it */
Expand All @@ -115,25 +122,29 @@ FWTPM_NV_HAL nvHal = {
};
FWTPM_NV_SetHAL(&ctx, &nvHal);

FWTPM_Init(&ctx);

/* Set custom IO transport after FWTPM_Init, which does not preserve the IO HAL */
Comment thread
dgarske marked this conversation as resolved.
/* Register a connectionless IO transport before initialization. */
FWTPM_IO_HAL ioHal = {
.send = spi_slave_send,
.recv = spi_slave_recv,
.wait = spi_slave_poll,
.accept = NULL, /* not connection-oriented */
.accept = NULL,
.close_conn = NULL,
.ctx = &spiHandle
};
FWTPM_IO_SetHAL(&ctx, &ioHal);

/* Initialize IO and run */
FWTPM_IO_Init(&ctx);
FWTPM_IO_ServerLoop(&ctx); /* blocks */

FWTPM_IO_Cleanup(&ctx);
FWTPM_Cleanup(&ctx);
rc = FWTPM_Init(&ctx);
if (rc == 0) {
rc = FWTPM_IO_Init(&ctx);
if (rc == 0) {
rc = FWTPM_IO_ServerLoop(&ctx); /* blocks */
FWTPM_IO_Cleanup(&ctx);
}
cleanupRc = FWTPM_Cleanup(&ctx);
if (rc == 0)
rc = cleanupRc;
}
return rc;
```

## Available Ports
Expand Down
4 changes: 2 additions & 2 deletions docs/fwtpm/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ scripts/tpm2_tools_test.sh
| Function | Description |
|----------|-------------|
| `int FWTPM_IO_SetHAL(FWTPM_CTX* ctx, FWTPM_IO_HAL* hal)` | Register custom IO transport callbacks |
| `int FWTPM_IO_Init(FWTPM_CTX* ctx)` | Initialize transport (sockets or custom HAL) |
| `int FWTPM_IO_Init(FWTPM_CTX* ctx)` | Initialize the custom HAL, TCP socket, or TIS transport |
| `void FWTPM_IO_Cleanup(FWTPM_CTX* ctx)` | Close transport and release resources |
| `int FWTPM_IO_ServerLoop(FWTPM_CTX* ctx)` | Main server loop; blocks until `ctx->running` is cleared |
| `int FWTPM_IO_ServerLoop(FWTPM_CTX* ctx)` | Run the selected transport loop; blocks until `ctx->running` is cleared |

### NV Storage (`fwtpm_nv.h`)

Expand Down
43 changes: 27 additions & 16 deletions docs/ja/fwtpm/hal-and-porting.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
# HAL と移植

fwTPM はハードウェア抽象化レイヤー (HAL) を提供しており、コアロジックを変更せずに組み込みターゲットへ移植できます。トランスポート用の IO HAL、永続ストレージ用の NV HAL、およびオプションのクロック HAL があります。複数のボード向けの完全なリファレンス移植は、[wolftpm-examples](https://github.com/wolfSSL/wolftpm-examples) リポジトリにあります。
fwTPM は、サーバートランスポート、永続ストレージ、プラットフォームクロック用のハードウェア抽象化レイヤー (HAL) を提供します。複数のボード向けの完全なリファレンス移植は、[wolftpm-examples](https://github.com/wolfSSL/wolftpm-examples) リポジトリにあります。

## IO HAL (トランスポート)

IO HAL は、fwTPM サーバーとそのクライアント間のトランスポートを抽象化します。デフォルトの実装は TCP ソケット (SWTPM プロトコル) を使用します。組み込みターゲットでは、SPI、I2C、UART、または共有メモリのコールバックに置き換えます。
IO HAL は、fwTPM サーバーとクライアント間のトランスポートを抽象化します。ソケットビルドでは、デフォルトで TCP ソケット (SWTPM プロトコル) を使用します。`FWTPM_IO_HAL` を登録すると、ソケットトランスポートは組み込み環境またはインプロセストランスポート用のコールバックに置き換わります。TIS ビルドでは、別の TIS HAL を使用します。

**コールバック構造体** (`fwtpm.h` で `FWTPM_IO_HAL` として定義):

| コールバック | シグネチャ | 説明 |
|----------|-----------|-------------|
| `send` | `int (*)(void* ctx, const void* buf, int sz)` | クライアントへデータを送信 |
| `recv` | `int (*)(void* ctx, void* buf, int sz)` | クライアントからデータを受信 |
| `wait` | `int (*)(void* ctx)` | データまたは接続を待機。ビットマスクを返す: `0x01`=コマンドデータ、`0x02`=プラットフォームデータ、`0x04`=新しいコマンド接続、`0x08`=新しいプラットフォーム接続 |
| `send` | `int (*)(void* ctx, int type, const void* buf, int sz)` | コマンドまたはプラットフォームクライアントへデータを送信 |
| `recv` | `int (*)(void* ctx, int type, void* buf, int sz)` | コマンドまたはプラットフォームクライアントからデータを受信 |
| `wait` | `int (*)(void* ctx, int timeoutMs)` | `timeoutMs` までデータまたは接続を待機。タイムアウト時は 0、それ以外はビットマスクを返す: `0x01`=コマンドデータ、`0x02`=プラットフォームデータ、`0x04`=新しいコマンド接続、`0x08`=新しいプラットフォーム接続 |
| `accept` | `int (*)(void* ctx, int type)` | 新しい接続を受け入れる (type: 0=コマンド、1=プラットフォーム) |
| `close_conn` | `void (*)(void* ctx, int type)` | 接続を閉じる (type: 0=コマンド、1=プラットフォーム) |
| `ctx` | `void*` | ユーザーコンテキストポインタ |

`type` 引数には `FWTPM_IO_TYPE_COMMAND` または `FWTPM_IO_TYPE_PLATFORM` を指定します。`send`、`recv`、`wait` コールバックは必須です。停止要求を検出できるように、`wait` は指定されたタイムアウトまでに戻る必要があります。デフォルトの 1000 ms 間隔は `FWTPM_IO_WAIT_TIMEOUT_MS` で変更できます。コネクションレス型トランスポートでは `accept` と `close_conn` を省略できます。`accept` を指定する場合は `close_conn` も指定し、`accept` がエラーを返す前に未完了の接続状態を解放する必要があります。

**登録:**

```c
FWTPM_IO_HAL myHal;
XMEMSET(&myHal, 0, sizeof(myHal));
myHal.send = my_send;
myHal.recv = my_recv;
myHal.wait = my_wait;
Expand All @@ -31,6 +34,8 @@ myHal.ctx = &myTransportCtx;
FWTPM_IO_SetHAL(&ctx, &myHal);
```

IO HAL は `FWTPM_Init()` の前、または `FWTPM_Init()` の後かつ `FWTPM_IO_Init()` の前に登録してください。

## NV HAL (永続ストレージ)

NV HAL は永続ストレージを抽象化します。デフォルトの実装はローカルファイル (`fwtpm_nv.bin`) を使用します。組み込みターゲットでは、フラッシュ、EEPROM、その他の不揮発性ストレージのコールバックに置き換えます。
Expand Down Expand Up @@ -101,10 +106,12 @@ FWTPM_NV_SetHAL(&ctx, &hal); /* before FWTPM_Init() */

## 移植の例

SPI トランスポートと SPI フラッシュの NV を使用するベアメタルの組み込みターゲットの例です。
ベアメタルターゲットでは、初期化前に SPI トランスポートと SPI フラッシュ NV のコールバックを登録できます。

```c
FWTPM_CTX ctx;
int cleanupRc;
int rc;
XMEMSET(&ctx, 0, sizeof(ctx));

/* Set custom NV storage before FWTPM_Init, which loads NV state through it */
Expand All @@ -115,25 +122,29 @@ FWTPM_NV_HAL nvHal = {
};
FWTPM_NV_SetHAL(&ctx, &nvHal);

FWTPM_Init(&ctx);

/* Set custom IO transport after FWTPM_Init, which does not preserve the IO HAL */
Comment thread
dgarske marked this conversation as resolved.
/* Register a connectionless IO transport before initialization. */
FWTPM_IO_HAL ioHal = {
.send = spi_slave_send,
.recv = spi_slave_recv,
.wait = spi_slave_poll,
.accept = NULL, /* not connection-oriented */
.accept = NULL,
.close_conn = NULL,
.ctx = &spiHandle
};
FWTPM_IO_SetHAL(&ctx, &ioHal);

/* Initialize IO and run */
FWTPM_IO_Init(&ctx);
FWTPM_IO_ServerLoop(&ctx); /* blocks */

FWTPM_IO_Cleanup(&ctx);
FWTPM_Cleanup(&ctx);
rc = FWTPM_Init(&ctx);
if (rc == 0) {
rc = FWTPM_IO_Init(&ctx);
if (rc == 0) {
rc = FWTPM_IO_ServerLoop(&ctx); /* blocks */
FWTPM_IO_Cleanup(&ctx);
}
cleanupRc = FWTPM_Cleanup(&ctx);
if (rc == 0)
rc = cleanupRc;
}
return rc;
```

## 利用可能な移植
Expand Down
6 changes: 3 additions & 3 deletions docs/ja/fwtpm/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,10 @@ scripts/tpm2_tools_test.sh

| 関数 | 説明 |
|----------|-------------|
| `int FWTPM_IO_SetHAL(FWTPM_CTX* ctx, FWTPM_IO_HAL* hal)` | カスタム IO トランスポートのコールバックを登録 |
| `int FWTPM_IO_Init(FWTPM_CTX* ctx)` | トランスポート (ソケットまたはカスタム HAL) を初期化 |
| `int FWTPM_IO_SetHAL(FWTPM_CTX* ctx, FWTPM_IO_HAL* hal)` | カスタム IO トランスポートコールバックを登録 |
| `int FWTPM_IO_Init(FWTPM_CTX* ctx)` | カスタム HAL、TCP ソケット、または TIS トランスポートを初期化 |
| `void FWTPM_IO_Cleanup(FWTPM_CTX* ctx)` | トランスポートを閉じ、リソースを解放 |
| `int FWTPM_IO_ServerLoop(FWTPM_CTX* ctx)` | メインのサーバーループ。`ctx->running` がクリアされるまでブロック |
| `int FWTPM_IO_ServerLoop(FWTPM_CTX* ctx)` | 選択されたトランスポートのサーバーループを実行。`ctx->running` がクリアされるまでブロック |

### NV ストレージ (`fwtpm_nv.h`)

Expand Down
36 changes: 31 additions & 5 deletions hal/tpm_io_atmel.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
#define SPI_BAUD_RATE_4M 21
#define CS_SPI_TPM 2

#ifndef WOLFTPM_ATMEL_SPI_POLL_TRIES
#define WOLFTPM_ATMEL_SPI_POLL_TRIES TPM_TIMEOUT_TRIES
#endif

/* Atmel ATSAM3X8EA Chip Selects */
static const byte Spi_CS[] = { 0, 1, 2, 3 };
static const byte Spi_PCS[] = { 0x0E, 0x0D, 0x0B, 0x07 };
Expand Down Expand Up @@ -89,16 +93,38 @@
return pcs;
}

static int WaitSPI_TPM(word32 statusMask)
{
word32 tries = WOLFTPM_ATMEL_SPI_POLL_TRIES;

while ((SPI0->SPI_SR & statusMask) == 0U) {
if (tries == 0U) {
return TPM_RC_FAILURE;
}
tries--;
}
return TPM_RC_SUCCESS;
}

static int XferSPI_TPM(byte pcs, const byte* pSendBuf, byte* pReadBuf, word16 wLen)
{
int ret = TPM_RC_SUCCESS;
word16 i;

for (i = 0; i < wLen; i++) {
while ((SPI0->SPI_SR & SPI_SR_TXEMPTY) == 0);
SPI0->SPI_TDR = (word16)pSendBuf[i] | (pcs << 16);
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
ret = WaitSPI_TPM(SPI_SR_TXEMPTY);
if (ret != TPM_RC_SUCCESS) {
break;
}
SPI0->SPI_TDR = (word16)pSendBuf[i] | (pcs << 16);
ret = WaitSPI_TPM(SPI_SR_TDRE);
if (ret != TPM_RC_SUCCESS) {
break;
}
ret = WaitSPI_TPM(SPI_SR_RDRF);
if (ret != TPM_RC_SUCCESS) {
break;
}
pReadBuf[i] = SPI0->SPI_RDR & 0x00FF;
}

Expand Down Expand Up @@ -136,7 +162,7 @@
#ifdef WOLFTPM_DEBUG_TIMEOUT
printf("SPI Ready Wait %d\n", TPM_SPI_WAIT_RETRY - timeout);
#endif
if (timeout <= 0) {
if (ret != TPM_RC_SUCCESS || timeout <= 0) {
SPI0->SPI_CR = SPI_CR_SPIDIS;
return TPM_RC_FAILURE;
}
Expand Down
12 changes: 6 additions & 6 deletions hal/tpm_io_espressif.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,8 @@ int TPM2_IoCb_Espressif_I2C(TPM2_CTX* ctx, int isRead, word32 addr,

/* If failures are encountered, try hardware reset of TPM device. */
#if defined(CONFIG_IDF_TARGET_ESP32S3)
#ifndef ESP_SPI_MAX_TRANSFER
#define ESP_SPI_MAX_TRANSFER_SIZE MAX_SPI_FRAMESIZE + 4
#ifndef ESP_SPI_MAX_TRANSFER_SIZE
#define ESP_SPI_MAX_TRANSFER_SIZE (MAX_SPI_FRAMESIZE + 4)
#endif
/* FSPI (HOST_SPI2) on esp32-s3-wroom */
#ifndef PIN_NUM_MISO
Expand All @@ -477,8 +477,8 @@ int TPM2_IoCb_Espressif_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
#define PIN_NUM_CS 10
#endif
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
#ifndef ESP_SPI_MAX_TRANSFER
#define ESP_SPI_MAX_TRANSFER_SIZE 1024
#ifndef ESP_SPI_MAX_TRANSFER_SIZE
#define ESP_SPI_MAX_TRANSFER_SIZE (1024)
#endif
#ifndef PIN_NUM_MISO
#define PIN_NUM_MISO 2
Expand All @@ -497,8 +497,8 @@ int TPM2_IoCb_Espressif_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
#define PIN_NUM_SPICS_IO -1
#endif
#else
#ifndef ESP_SPI_MAX_TRANSFER
#define ESP_SPI_MAX_TRANSFER_SIZE MAX_SPI_FRAMESIZE
#ifndef ESP_SPI_MAX_TRANSFER_SIZE
#define ESP_SPI_MAX_TRANSFER_SIZE (MAX_SPI_FRAMESIZE)
#endif
#ifndef PIN_NUM_MISO
#error PIN_NUM_MISO undefined
Expand Down
8 changes: 4 additions & 4 deletions hal/tpm_io_fwtpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ int FWTPM_TIS_ClientConnect(FWTPM_TIS_CLIENT_CTX* client)
(void)fdFlags;
#endif

/* Authenticate the data-bearing endpoint before mapping it. Named
* semaphores carry wakeups only and are derived from this validated file
* owner below. */
/* Authenticate the data-bearing endpoint before mapping it. The named
* semaphores carry wakeups only and use fixed, host-wide names; trust
* comes from validating the shared-memory file below. */
if (fstat(fd, &st) != 0) {
#ifdef DEBUG_WOLFTPM
printf("fwTPM HAL: fstat(%s) failed: %d (%s)\n",
Expand Down Expand Up @@ -255,7 +255,7 @@ int FWTPM_TIS_ClientConnect(FWTPM_TIS_CLIENT_CTX* client)
}

/* Reject a replaced pathname or metadata change after opening the
* per-owner semaphore pair. */
* fixed-name semaphore pair. */
if (fstat(fd, &st) != 0 ||
FWTPM_TIS_ClientValidateShm(&st) != TPM_RC_SUCCESS ||
lstat(FWTPM_TIS_SHM_PATH, &pathSt) != 0 ||
Expand Down
Loading
Loading