Skip to content

Commit 0c92258

Browse files
committed
nvm_flash: checks object boundaries in reads
1 parent 4548249 commit 0c92258

3 files changed

Lines changed: 89 additions & 38 deletions

File tree

src/wh_nvm_flash.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,15 @@ static int nfObject_ReadDataBytes(whNvmFlashContext* context, int partition,
664664
start = context->directory.objects[object_index].state.start;
665665
startOffset = nfPartition_DataOffset(context, partition) + start;
666666

667+
/* object bounds checks, do both to avoid integer overflow checks */
668+
if (byte_offset >= (context->directory.objects[object_index].metadata.len)) {
669+
return WH_ERROR_BADARGS;
670+
}
671+
if ((byte_offset + byte_count) >
672+
(context->directory.objects[object_index].metadata.len)) {
673+
return WH_ERROR_BADARGS;
674+
}
675+
667676
/* Ensure we don't read off the end of the active partition */
668677
if (WH_ERROR_OK != nfPartition_CheckDataRange(context, partition,
669678
startOffset * WHFU_BYTES_PER_UNIT + byte_offset,

src/wh_server_cert.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,6 @@ int wh_Server_CertReadTrusted(whServerContext* server, whNvmId id,
228228
uint8_t* cert, uint32_t* inout_cert_len)
229229
{
230230
int rc;
231-
whNvmSize userLen;
232231
whNvmMetadata meta;
233232

234233
if ((server == NULL) || (cert == NULL) || (inout_cert_len == NULL) ||
@@ -243,17 +242,16 @@ int wh_Server_CertReadTrusted(whServerContext* server, whNvmId id,
243242
return rc;
244243
}
245244

246-
/* Clamp the input length to the actual length of the certificate. This will
247-
* be reflected back to the user on length mismatch failure */
248-
userLen = *inout_cert_len;
249-
*inout_cert_len = meta.len;
250-
251245
/* Check if the provided buffer is large enough */
252-
if (meta.len > userLen) {
246+
if (meta.len > *inout_cert_len) {
253247
return WH_ERROR_BUFFER_SIZE;
254248
}
255249

256-
return wh_Nvm_Read(server->nvm, id, 0, userLen, cert);
250+
/* Clamp the input length to the actual length of the certificate. This will
251+
* be reflected back to the user on length mismatch failure */
252+
*inout_cert_len = meta.len;
253+
254+
return wh_Nvm_Read(server->nvm, id, 0, meta.len, cert);
257255
}
258256

259257
/* Verify a certificate against trusted certificates */

src/wh_server_nvm.c

Lines changed: 74 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,46 @@
4343
#include "wolfhsm/wh_server.h"
4444
#include "wolfhsm/wh_server_nvm.h"
4545

46+
/* Handle NVM read, do access checking and clamping */
47+
static int _HandleNvmRead(whServerContext* server, uint8_t* out_data,
48+
whNvmSize offset, whNvmSize len, whNvmSize* out_len,
49+
whNvmId id)
50+
{
51+
whNvmMetadata meta;
52+
int32_t rc;
53+
54+
if ((server == NULL) || (out_data == NULL) || (out_len == NULL)) {
55+
return WH_ERROR_BADARGS;
56+
}
57+
58+
if (len > WH_MESSAGE_NVM_MAX_READ_LEN) {
59+
return WH_ERROR_ABORTED;
60+
}
61+
62+
rc = wh_Nvm_GetMetadata(server->nvm, id, &meta);
63+
if (rc != WH_ERROR_OK) {
64+
return rc;
65+
}
66+
67+
if (meta.flags & WH_NVM_FLAGS_NONEXPORTABLE) {
68+
return WH_ERROR_ACCESS;
69+
}
70+
71+
if (offset >= meta.len)
72+
return WH_ERROR_BADARGS;
73+
74+
/* Clamp length to object size */
75+
if ((offset + len) > meta.len) {
76+
len = meta.len - offset;
77+
}
78+
79+
rc = wh_Nvm_Read(server->nvm, id, offset, len, out_data);
80+
if (rc != WH_ERROR_OK)
81+
return rc;
82+
*out_len = len;
83+
return WH_ERROR_OK;
84+
}
85+
4686
int wh_Server_HandleNvmRequest(whServerContext* server,
4787
uint16_t magic, uint16_t action, uint16_t seq,
4888
uint16_t req_size, const void* req_packet,
@@ -240,44 +280,30 @@ int wh_Server_HandleNvmRequest(whServerContext* server,
240280

241281
case WH_MESSAGE_NVM_ACTION_READ:
242282
{
243-
whMessageNvm_ReadRequest req = {0};
244-
whMessageNvm_ReadResponse resp = {0};
245-
uint16_t hdr_len = sizeof(resp);
246-
uint8_t* data = (uint8_t*)resp_packet + hdr_len;
247-
uint16_t data_len = 0;
248-
whNvmMetadata meta = {0};
283+
whMessageNvm_ReadRequest req = {0};
284+
whMessageNvm_ReadResponse resp = {0};
285+
uint16_t hdr_len = sizeof(resp);
286+
uint8_t* data = (uint8_t*)resp_packet + hdr_len;
287+
whNvmSize data_len = 0;
249288

250289
if (req_size != sizeof(req)) {
251290
/* Request is malformed */
252291
resp.rc = WH_ERROR_ABORTED;
253-
} else {
292+
}
293+
else {
254294
/* Convert request struct */
255-
wh_MessageNvm_TranslateReadRequest(magic,
256-
(whMessageNvm_ReadRequest*)req_packet, &req);
295+
wh_MessageNvm_TranslateReadRequest(
296+
magic, (whMessageNvm_ReadRequest*)req_packet, &req);
257297

258-
if (req.data_len > WH_MESSAGE_NVM_MAX_READ_LEN) {
259-
resp.rc = WH_ERROR_ABORTED;
260-
} else {
261-
/* Check metadata for non-exportable flag */
262-
resp.rc = wh_Nvm_GetMetadata(server->nvm, req.id, &meta);
263-
if (resp.rc == 0) {
264-
if (meta.flags & WH_NVM_FLAGS_NONEXPORTABLE) {
265-
resp.rc = WH_ERROR_ACCESS;
266-
}
267-
else {
268-
/* Process the Read action */
269-
resp.rc = wh_Nvm_Read(server->nvm, req.id, req.offset,
270-
req.data_len, data);
271-
if (resp.rc == 0) {
272-
data_len = req.data_len;
273-
}
274-
}
275-
}
298+
resp.rc = _HandleNvmRead(server, data, req.offset, req.data_len,
299+
&req.data_len, req.id);
300+
if (resp.rc == WH_ERROR_OK) {
301+
data_len = req.data_len;
276302
}
277303
}
278304
/* Convert the response struct */
279-
wh_MessageNvm_TranslateReadResponse(magic,
280-
&resp, (whMessageNvm_ReadResponse*)resp_packet);
305+
wh_MessageNvm_TranslateReadResponse(
306+
magic, &resp, (whMessageNvm_ReadResponse*)resp_packet);
281307
*out_resp_size = sizeof(resp) + data_len;
282308
}; break;
283309

@@ -338,6 +364,7 @@ int wh_Server_HandleNvmRequest(whServerContext* server,
338364
whMessageNvm_ReadDmaRequest req = {0};
339365
whMessageNvm_SimpleResponse resp = {0};
340366
whNvmMetadata meta = {0};
367+
whNvmSize read_len;
341368
void* data = NULL;
342369

343370
if (req_size != sizeof(req)) {
@@ -355,6 +382,23 @@ int wh_Server_HandleNvmRequest(whServerContext* server,
355382
resp.rc = WH_ERROR_ACCESS;
356383
}
357384
}
385+
386+
if (resp.rc == 0) {
387+
if (req.offset >= meta.len) {
388+
resp.rc = WH_ERROR_BADARGS;
389+
}
390+
}
391+
392+
if (resp.rc == 0) {
393+
read_len = req.data_len;
394+
/* Clamp length to object size */
395+
if ((req.offset + read_len) > meta.len) {
396+
read_len = meta.len - req.offset;
397+
}
398+
}
399+
400+
/* use unclamped legnth for DMA address processing in case DMA callbacks
401+
* are sensible to alignment and/or size */
358402
if (resp.rc == 0) {
359403
/* perform platform-specific host address processing */
360404
resp.rc = wh_Server_DmaProcessClientAddress(
@@ -363,7 +407,7 @@ int wh_Server_HandleNvmRequest(whServerContext* server,
363407
}
364408
if (resp.rc == 0) {
365409
/* Process the Read action */
366-
resp.rc = wh_Nvm_Read(server->nvm, req.id, req.offset, req.data_len,
410+
resp.rc = wh_Nvm_Read(server->nvm, req.id, req.offset, read_len,
367411
(uint8_t*)data);
368412
}
369413
if (resp.rc == 0) {

0 commit comments

Comments
 (0)