Skip to content
Open
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
6 changes: 2 additions & 4 deletions benchmark/wh_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,9 +1071,7 @@ int wh_Bench_ClientServer_Posix(int transport, int moduleIndex)

#ifndef WOLFHSM_CFG_NO_CRYPTO
/* Crypto context */
whServerCryptoContext crypto[1] = {{
.devId = INVALID_DEVID,
}};
whServerCryptoContext crypto[1] = {0};
#endif

/* Set up server configuration with NVM and crypto */
Expand Down Expand Up @@ -1109,7 +1107,7 @@ int wh_Bench_ClientServer_Posix(int transport, int moduleIndex)
}

/* Initialize RNG */
ret = wc_InitRng_ex(crypto->rng, NULL, crypto->devId);
ret = wc_InitRng_ex(crypto->rng, NULL, INVALID_DEVID);
if (ret != 0) {
WH_BENCH_PRINTF("Failed to initialize RNG: %d\n", ret);
wolfCrypt_Cleanup();
Expand Down
94 changes: 94 additions & 0 deletions docs/draft/crypto_affinity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Crypto Affinity Client API

The crypto affinity feature allows a client to control whether the server uses **software** or **hardware** cryptographic implementations on a per-request basis.

Affinity is stored as **client-local state** and is transmitted to the server in every crypto request message header. There is no dedicated round-trip required to change affinity -- setting it is instantaneous and takes effect on the next crypto operation. Affinity persists for all subsequent requests once changed.

## Affinity Values

```c
enum WH_CRYPTO_AFFINITY_ENUM {
WH_CRYPTO_AFFINITY_HW = 0, // Attempt to use hardware crypto (devId = configured value)
WH_CRYPTO_AFFINITY_SW = 1, // Use software crypto (devId = INVALID_DEVID)
};
```

The default affinity after client initialization is `WH_CRYPTO_AFFINITY_HW`.

## API

### SetCryptoAffinity

```c
int wh_Client_SetCryptoAffinity(whClientContext* c, uint32_t affinity);
```

Sets the client's crypto affinity. This is a **local operation** that does not communicate with the server. The new affinity value will be included in all subsequent crypto request messages.

**Parameters:**
- `c` -- Client context
- `affinity` -- `WH_CRYPTO_AFFINITY_SW` or `WH_CRYPTO_AFFINITY_HW`

**Returns:**
- `WH_ERROR_OK` -- Affinity set successfully
- `WH_ERROR_BADARGS` -- NULL context or invalid affinity value

### GetCryptoAffinity

```c
int wh_Client_GetCryptoAffinity(whClientContext* c, uint32_t* out_affinity);
```

Retrieves the client's current crypto affinity. This is a **local operation** that does not communicate with the server.

**Parameters:**
- `c` -- Client context
- `out_affinity` -- Pointer to receive the current affinity value

**Returns:**
- `WH_ERROR_OK` -- Affinity retrieved successfully
- `WH_ERROR_BADARGS` -- NULL context or NULL output pointer

## Usage Example

```c
uint32_t affinity;

/* Default affinity is WH_CRYPTO_AFFINITY_SW after wh_Client_Init() */
wh_Client_GetCryptoAffinity(client, &affinity);
/* affinity == WH_CRYPTO_AFFINITY_SW */

/* Switch to hardware crypto -- takes effect immediately, no round-trip */
int rc = wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_HW);
if (rc == WH_ERROR_OK) {
/* All subsequent crypto operations will request HW acceleration */
}

/* Perform a crypto operation -- affinity is sent in the request header */
wc_AesCbcEncrypt(&aes, out, in, len);
/* If server has a valid devId, hardware crypto callback is used */

/* Switch back to software crypto */
wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_SW);
/* Subsequent crypto operations use software implementation */
Comment on lines +57 to +73
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 57 states the default affinity after wh_Client_Init() is WH_CRYPTO_AFFINITY_SW, but the code initializes whClientContext_t.cryptoAffinity to zero (via {0} initialization throughout the codebase), and WH_CRYPTO_AFFINITY_HW = 0. Both the PR description and the test code (e.g., wh_test_crypto_affinity.c line 211) confirm the default is WH_CRYPTO_AFFINITY_HW. The comment and the assertion on line 59 are incorrect.

Suggested change
/* Default affinity is WH_CRYPTO_AFFINITY_SW after wh_Client_Init() */
wh_Client_GetCryptoAffinity(client, &affinity);
/* affinity == WH_CRYPTO_AFFINITY_SW */
/* Switch to hardware crypto -- takes effect immediately, no round-trip */
int rc = wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_HW);
if (rc == WH_ERROR_OK) {
/* All subsequent crypto operations will request HW acceleration */
}
/* Perform a crypto operation -- affinity is sent in the request header */
wc_AesCbcEncrypt(&aes, out, in, len);
/* If server has a valid devId, hardware crypto callback is used */
/* Switch back to software crypto */
wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_SW);
/* Subsequent crypto operations use software implementation */
/* Default affinity is WH_CRYPTO_AFFINITY_HW after wh_Client_Init() */
wh_Client_GetCryptoAffinity(client, &affinity);
/* affinity == WH_CRYPTO_AFFINITY_HW */
/* Switch to software crypto -- takes effect immediately, no round-trip */
int rc = wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_SW);
if (rc == WH_ERROR_OK) {
/* All subsequent crypto operations will request software implementation */
}
/* Perform a crypto operation -- affinity is sent in the request header */
wc_AesCbcEncrypt(&aes, out, in, len);
/* If server has a valid devId, hardware crypto callback is used when affinity is HW */
/* Switch back to hardware crypto */
wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_HW);
/* Subsequent crypto operations will again request HW acceleration */

Copilot uses AI. Check for mistakes.
```

## Server Behavior

When the server receives a crypto request, it reads the affinity field from the generic crypto request header and selects the appropriate `devId`:

| Affinity in Request | Server Action |
|---------------------|---------------|
| `WH_CRYPTO_AFFINITY_SW` | Uses `INVALID_DEVID` (wolfCrypt software implementation) |
| `WH_CRYPTO_AFFINITY_HW` | Uses `server->defaultDevId` if valid, otherwise falls back to `INVALID_DEVID` |

The `defaultDevId` is configured at server initialization from `config->devId`. If the server was not configured with a valid hardware `devId`, hardware affinity requests will silently fall back to software crypto.

## Protocol Details

Affinity is transmitted in the `affinity` field of `whMessageCrypto_GenericRequestHeader`, which is included at the start of every crypto request message. This means:

- Each crypto operation independently specifies its desired affinity
- Multiple clients can use different affinities concurrently without interference
- No server-side affinity state is maintained per-client
- Changing affinity has zero latency (no communication overhead)
7 changes: 3 additions & 4 deletions docs/src-ja/chapter03.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,14 @@ whNvmContext nvmCtx = {0};
wh_Nvm_Init(&nvmCtx, &whNvmConfig);

/* 手順3: 暗号コンテキスト構造体の割り当てと初期化 */
whServerCryptoContext cryptoCtx {
.devID = INVALID_DEVID; /* あるいは、カスタム暗号コールバックdevIDを設定 */
};
whServerCryptoContext cryptoCtx = {0};

/* サーバー設定の割り当てと初期化 */
whServerConfig serverCfg = {
.comm = commServerCfg,
.nvm = nvmCtx,
.crypto = cryptoCtx,
.crypto = &cryptoCtx,
.devId = INVALID_DEVID, /* あるいは、カスタム暗号コールバックdevIDを設定 */
};

/* 手順4: wolfCryptの初期化 */
Expand Down
7 changes: 3 additions & 4 deletions docs/src/chapter03.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,14 @@ 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 */
};
whServerCryptoContext cryptoCtx = {0};

/* Allocate and initialize the Server configuration*/
whServerConfig serverCfg = {
.comm = commServerCfg,
.nvm = nvmCtx,
.crypto = cryptoCtx,
.crypto = &cryptoCtx,
.devId = INVALID_DEVID, /* or set to custom crypto callback devID */
};

/* Step 4: Initialize wolfCrypt*/
Expand Down
13 changes: 6 additions & 7 deletions examples/posix/wh_posix_server/wh_posix_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,7 @@ int main(int argc, char** argv)
}
#if !defined(WOLFHSM_CFG_NO_CRYPTO)
/* Crypto context */
whServerCryptoContext crypto[1] = {{
.devId = INVALID_DEVID,
}};
whServerCryptoContext crypto[1] = {0};

#if defined(WOLFHSM_CFG_SHE_EXTENSION)
whServerSheContext she[1] = {{0}};
Expand Down Expand Up @@ -452,11 +450,12 @@ int main(int argc, char** argv)
wh_Utils_Hexdump("Context 4: Server HW RNG:\n", buffer, sizeof(buffer));

/* Context 5: Set default server crypto to use cryptocb */
crypto->devId = HW_DEV_ID;
WOLFHSM_CFG_PRINTF("Context 5: Setting up default server crypto with devId=%d\n",
crypto->devId);
s_conf->devId = HW_DEV_ID;
WOLFHSM_CFG_PRINTF(
"Context 5: Setting up default server crypto with devId=%d\n",
s_conf->devId);

rc = wc_InitRng_ex(crypto->rng, NULL, crypto->devId);
rc = wc_InitRng_ex(crypto->rng, NULL, s_conf->devId);
if (rc != 0) {
WOLFHSM_CFG_PRINTF("Failed to wc_InitRng_ex: %d\n", rc);
return rc;
Expand Down
22 changes: 22 additions & 0 deletions src/wh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,28 @@ int wh_Client_CommInfo(whClientContext* c,
return rc;
}

int wh_Client_SetCryptoAffinity(whClientContext* c, uint32_t affinity)
{
if (c == NULL) {
return WH_ERROR_BADARGS;
}
if (affinity != WH_CRYPTO_AFFINITY_SW &&
affinity != WH_CRYPTO_AFFINITY_HW) {
return WH_ERROR_BADARGS;
}
c->cryptoAffinity = affinity;
return WH_ERROR_OK;
}

int wh_Client_GetCryptoAffinity(whClientContext* c, uint32_t* out_affinity)
{
if (c == NULL || out_affinity == NULL) {
return WH_ERROR_BADARGS;
}
*out_affinity = c->cryptoAffinity;
return WH_ERROR_OK;
}


int wh_Client_CommCloseRequest(whClientContext* c)
{
Expand Down
Loading
Loading