@@ -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