Skip to content

Commit 97fe4ed

Browse files
committed
added async RNG
1 parent 655e1c9 commit 97fe4ed

5 files changed

Lines changed: 539 additions & 94 deletions

File tree

src/wh_client_crypto.c

Lines changed: 166 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -175,155 +175,229 @@ static int _getCryptoResponse(uint8_t* respBuf, uint16_t type,
175175
}
176176

177177
/** Implementations */
178-
int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size)
178+
int wh_Client_RngGenerateRequest(whClientContext* ctx, uint32_t size)
179179
{
180-
int ret = WH_ERROR_OK;
181-
whMessageCrypto_RngRequest* req;
182-
whMessageCrypto_RngResponse* res;
183-
uint8_t* dataPtr;
184-
uint8_t* reqData;
180+
whMessageCrypto_RngRequest* req;
181+
uint8_t* dataPtr;
182+
uint16_t req_len;
185183

186-
if (ctx == NULL) {
184+
if (ctx == NULL || size == 0) {
185+
return WH_ERROR_BADARGS;
186+
}
187+
if (size > WH_MESSAGE_CRYPTO_RNG_MAX_INLINE_SZ) {
187188
return WH_ERROR_BADARGS;
188189
}
189190

190-
/* Get data buffer */
191191
dataPtr = wh_CommClient_GetDataPtr(ctx->comm);
192192
if (dataPtr == NULL) {
193193
return WH_ERROR_BADARGS;
194194
}
195195

196-
/* Setup generic header and get pointer to request data */
197-
reqData =
198-
_createCryptoRequest(dataPtr, WC_ALGO_TYPE_RNG, ctx->cryptoAffinity);
196+
req = (whMessageCrypto_RngRequest*)_createCryptoRequest(
197+
dataPtr, WC_ALGO_TYPE_RNG, ctx->cryptoAffinity);
198+
req->sz = size;
199199

200-
/* Setup request header */
201-
req = (whMessageCrypto_RngRequest*)reqData;
200+
req_len =
201+
(uint16_t)(sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req));
202202

203-
/* Calculate maximum data size client can request (subtract headers) */
204-
const uint32_t client_max_data =
205-
WOLFHSM_CFG_COMM_DATA_LEN -
206-
sizeof(whMessageCrypto_GenericRequestHeader) -
207-
sizeof(whMessageCrypto_RngRequest);
203+
WH_DEBUG_CLIENT_VERBOSE("RNG req: size=%u\n", (unsigned int)size);
208204

209-
while ((size > 0) && (ret == WH_ERROR_OK)) {
210-
/* Request Message */
211-
uint16_t group = WH_MESSAGE_GROUP_CRYPTO;
212-
uint16_t action = WC_ALGO_TYPE_RNG;
213-
uint16_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) +
214-
sizeof(whMessageCrypto_RngRequest);
215-
uint16_t res_len;
205+
return wh_Client_SendRequest(ctx, WH_MESSAGE_GROUP_CRYPTO, WC_ALGO_TYPE_RNG,
206+
req_len, dataPtr);
207+
}
216208

217-
/* Request up to client max, but no more than remaining size */
218-
uint32_t chunk_size = (size < client_max_data) ? size : client_max_data;
219-
req->sz = chunk_size;
209+
int wh_Client_RngGenerateResponse(whClientContext* ctx, uint8_t* out,
210+
uint32_t* inout_size)
211+
{
212+
int ret;
213+
uint16_t group;
214+
uint16_t action;
215+
uint16_t res_len = 0;
216+
uint8_t* dataPtr;
217+
whMessageCrypto_RngResponse* res = NULL;
220218

221-
WH_DEBUG_CLIENT_VERBOSE("RNG: size:%u reqsz:%u remaining:%u\n",
222-
(unsigned int)chunk_size, (unsigned int)req_len,
223-
(unsigned int)size);
224-
WH_DEBUG_CLIENT_VERBOSE("RNG: req:%p\n", req);
219+
if (ctx == NULL || inout_size == NULL ||
220+
(out == NULL && *inout_size != 0)) {
221+
return WH_ERROR_BADARGS;
222+
}
225223

226-
/* Send request and get response */
227-
ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr);
228-
if (ret == 0) {
229-
do {
230-
ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len,
231-
dataPtr);
232-
} while (ret == WH_ERROR_NOTREADY);
224+
dataPtr = wh_CommClient_GetDataPtr(ctx->comm);
225+
if (dataPtr == NULL) {
226+
return WH_ERROR_BADARGS;
227+
}
228+
229+
ret = wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr);
230+
if (ret != WH_ERROR_OK) {
231+
return ret;
232+
}
233+
234+
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_RNG, (uint8_t**)&res);
235+
if (ret == WH_ERROR_OK) {
236+
if (res->sz > *inout_size) {
237+
/* Server returned more than the caller's buffer can hold */
238+
ret = WH_ERROR_ABORTED;
233239
}
234-
if (ret == WH_ERROR_OK) {
235-
/* Get response */
236-
ret =
237-
_getCryptoResponse(dataPtr, WC_ALGO_TYPE_RNG, (uint8_t**)&res);
238-
if (ret == WH_ERROR_OK) {
239-
/* Validate server didn't respond with more than requested */
240-
if (res->sz <= chunk_size) {
241-
uint8_t* res_out = (uint8_t*)(res + 1);
242-
if (out != NULL) {
243-
memcpy(out, res_out, res->sz);
244-
out += res->sz;
245-
}
246-
size -= res->sz;
247-
WH_DEBUG_CLIENT_VERBOSE("out size:%u remaining:%u\n",
248-
(unsigned int)res->sz, (unsigned int)size);
249-
WH_DEBUG_VERBOSE_HEXDUMP("[client] res_out: \n", out - res->sz,
250-
res->sz);
251-
}
252-
else {
253-
/* Server returned more than we can handle - error */
254-
ret = WH_ERROR_ABORTED;
255-
}
240+
else {
241+
if (res->sz > 0 && out != NULL) {
242+
memcpy(out, (uint8_t*)(res + 1), res->sz);
256243
}
244+
*inout_size = res->sz;
245+
WH_DEBUG_CLIENT_VERBOSE("RNG resp: size=%u\n",
246+
(unsigned int)res->sz);
257247
}
258248
}
259249
return ret;
260250
}
261251

252+
int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size)
253+
{
254+
int ret = WH_ERROR_OK;
255+
uint32_t remaining;
256+
const uint32_t cap = (uint32_t)WH_MESSAGE_CRYPTO_RNG_MAX_INLINE_SZ;
257+
258+
if (ctx == NULL || out == NULL) {
259+
return WH_ERROR_BADARGS;
260+
}
261+
262+
remaining = size;
263+
while (ret == WH_ERROR_OK && remaining > 0) {
264+
uint32_t chunk = (remaining < cap) ? remaining : cap;
265+
uint32_t got = chunk;
266+
267+
ret = wh_Client_RngGenerateRequest(ctx, chunk);
268+
if (ret != WH_ERROR_OK) {
269+
break;
270+
}
271+
do {
272+
ret = wh_Client_RngGenerateResponse(ctx, out, &got);
273+
} while (ret == WH_ERROR_NOTREADY);
274+
if (ret != WH_ERROR_OK) {
275+
break;
276+
}
277+
if (got == 0) {
278+
/* Server returned nothing for a non-zero request — guard against
279+
* infinite loop. */
280+
ret = WH_ERROR_ABORTED;
281+
break;
282+
}
283+
out += got;
284+
remaining -= got;
285+
}
286+
return ret;
287+
}
288+
262289
#ifdef WOLFHSM_CFG_DMA
263-
int wh_Client_RngGenerateDma(whClientContext* ctx, uint8_t* out, uint32_t size)
290+
int wh_Client_RngGenerateDmaRequest(whClientContext* ctx, uint8_t* out,
291+
uint32_t size)
264292
{
265-
int ret = WH_ERROR_OK;
266-
uint8_t* dataPtr = NULL;
267-
whMessageCrypto_RngDmaRequest* req = NULL;
268-
whMessageCrypto_RngDmaResponse* resp = NULL;
269-
uint16_t respSz = 0;
270-
uintptr_t outAddr = 0;
293+
int ret = WH_ERROR_OK;
294+
uint8_t* dataPtr = NULL;
295+
whMessageCrypto_RngDmaRequest* req = NULL;
296+
uintptr_t outAddr = 0;
297+
bool outAddrAcquired = false;
271298

272-
if ((ctx == NULL) || (out == NULL) || (size == 0)) {
299+
if (ctx == NULL || out == NULL || size == 0) {
273300
return WH_ERROR_BADARGS;
274301
}
302+
/* Fail-fast on occupied transport to avoid acquiring a DMA mapping that
303+
* would be leaked if SendRequest later rejects the request. */
304+
if (wh_CommClient_IsRequestPending(ctx->comm) == 1) {
305+
return WH_ERROR_REQUEST_PENDING;
306+
}
275307

276-
/* Get data pointer from the context to use as request/response storage */
277308
dataPtr = (uint8_t*)wh_CommClient_GetDataPtr(ctx->comm);
278309
if (dataPtr == NULL) {
279310
return WH_ERROR_BADARGS;
280311
}
281312

282-
/* Setup generic header and get pointer to request data */
283313
req = (whMessageCrypto_RngDmaRequest*)_createCryptoRequest(
284314
dataPtr, WC_ALGO_TYPE_RNG, ctx->cryptoAffinity);
285315

286-
/* Set up output buffer address and size */
287-
req->output.sz = size;
316+
req->output.sz = size;
317+
req->output.addr = 0;
288318

289-
/* Perform address translation for output buffer (PRE operation) */
319+
/* PRE address translation for the output buffer */
290320
ret = wh_Client_DmaProcessClientAddress(
291-
ctx, (uintptr_t)out, (void**)&outAddr, req->output.sz,
321+
ctx, (uintptr_t)out, (void**)&outAddr, size,
292322
WH_DMA_OPER_CLIENT_WRITE_PRE, (whDmaFlags){0});
293323
if (ret == WH_ERROR_OK) {
324+
outAddrAcquired = true;
294325
req->output.addr = outAddr;
295326
}
296327

297328
if (ret == WH_ERROR_OK) {
298-
/* Send the request to the server */
329+
/* Stash for POST cleanup in the matching Response */
330+
ctx->dma.asyncCtx.rng.outAddr = outAddr;
331+
ctx->dma.asyncCtx.rng.clientAddr = (uintptr_t)out;
332+
ctx->dma.asyncCtx.rng.outSz = size;
333+
299334
ret = wh_Client_SendRequest(
300335
ctx, WH_MESSAGE_GROUP_CRYPTO_DMA, WC_ALGO_TYPE_RNG,
301336
sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req),
302-
(uint8_t*)dataPtr);
337+
dataPtr);
303338
}
304339

305-
if (ret == WH_ERROR_OK) {
306-
/* Wait for and receive the response */
307-
do {
308-
ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz,
309-
(uint8_t*)dataPtr);
310-
} while (ret == WH_ERROR_NOTREADY);
340+
if (ret != WH_ERROR_OK && outAddrAcquired) {
341+
/* Release the mapping if SendRequest failed; the Response will not run
342+
* and the stash is meaningless. */
343+
(void)wh_Client_DmaProcessClientAddress(
344+
ctx, (uintptr_t)out, (void**)&outAddr, size,
345+
WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0});
346+
ctx->dma.asyncCtx.rng.outSz = 0;
347+
}
348+
return ret;
349+
}
350+
351+
int wh_Client_RngGenerateDmaResponse(whClientContext* ctx)
352+
{
353+
int ret = WH_ERROR_OK;
354+
uint8_t* dataPtr = NULL;
355+
whMessageCrypto_RngDmaResponse* resp = NULL;
356+
uint16_t respSz = 0;
357+
358+
if (ctx == NULL) {
359+
return WH_ERROR_BADARGS;
360+
}
361+
362+
dataPtr = (uint8_t*)wh_CommClient_GetDataPtr(ctx->comm);
363+
if (dataPtr == NULL) {
364+
return WH_ERROR_BADARGS;
365+
}
366+
367+
ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz, dataPtr);
368+
if (ret == WH_ERROR_NOTREADY) {
369+
return ret;
311370
}
312371

313372
if (ret == WH_ERROR_OK) {
314-
/* Get response structure pointer, validates generic header rc */
315373
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_RNG, (uint8_t**)&resp);
316-
/* Nothing more to do on success, as server will have written random
317-
* bytes directly to client memory */
374+
/* On success, server has written random bytes directly to client
375+
* memory — nothing else to copy. */
318376
}
319377

320-
/* Perform address translation cleanup (POST operation)
321-
* This is called regardless of successful operation to give the callback a
322-
* chance for cleanup */
323-
(void)wh_Client_DmaProcessClientAddress(
324-
ctx, (uintptr_t)out, (void**)&outAddr, size,
325-
WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0});
378+
/* POST DMA cleanup using stashed addresses (runs on every non-NOTREADY
379+
* exit so the client buffer is safe to read regardless of error). */
380+
if (ctx->dma.asyncCtx.rng.outSz > 0) {
381+
uintptr_t outAddr = ctx->dma.asyncCtx.rng.outAddr;
382+
(void)wh_Client_DmaProcessClientAddress(
383+
ctx, ctx->dma.asyncCtx.rng.clientAddr, (void**)&outAddr,
384+
ctx->dma.asyncCtx.rng.outSz, WH_DMA_OPER_CLIENT_WRITE_POST,
385+
(whDmaFlags){0});
386+
ctx->dma.asyncCtx.rng.outSz = 0;
387+
}
388+
return ret;
389+
}
390+
391+
int wh_Client_RngGenerateDma(whClientContext* ctx, uint8_t* out, uint32_t size)
392+
{
393+
int ret;
326394

395+
ret = wh_Client_RngGenerateDmaRequest(ctx, out, size);
396+
if (ret == WH_ERROR_OK) {
397+
do {
398+
ret = wh_Client_RngGenerateDmaResponse(ctx);
399+
} while (ret == WH_ERROR_NOTREADY);
400+
}
327401
return ret;
328402
}
329403
#endif /* WOLFHSM_CFG_DMA */

0 commit comments

Comments
 (0)