Skip to content
Merged
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_HW after wh_Client_Init() */
wh_Client_GetCryptoAffinity(client, &affinity);
/* affinity == WH_CRYPTO_AFFINITY_HW */

/* 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 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 use software implementation */
}

/* Switch back to hardware crypto */
wh_Client_SetCryptoAffinity(client, WH_CRYPTO_AFFINITY_HW);
/* Subsequent crypto operations request HW acceleration */
```

## 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->devId` if valid, otherwise falls back to `INVALID_DEVID` |

The `devId` 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