Skip to content

Commit 8e27558

Browse files
committed
Add PSA support in old update client
1. Add configuration UPDATE_CLIENT_STORAGE_PSA for PSA Firmware Update 2. Fix compile errors for PSA targets having no ARM_UC_FEATURE_PAL_FLASHIAP support 3. Support in-transit hash validation for targets like PSA having no read permission and unable to do read-back hash validation from storage
1 parent d7edc52 commit 8e27558

File tree

3 files changed

+96
-76
lines changed

3 files changed

+96
-76
lines changed

update-client-hub/mbed_lib.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
"delta-storage-size": {
6767
"help": "Total storage allocated for delta image. This config item is only for multicast update.",
6868
"value": null
69+
},
70+
"in-transit-hash-validation": {
71+
"help": "Calculate payload hash in transit and not by reading back from storage. Useful on platforms without read permission.",
72+
"value": 0
6973
}
7074
}
7175
}

update-client-hub/modules/common/update-client-common/arm_uc_config.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,18 @@ ARM_UC_FEATURE_SIMPLE_COAP_SOURCE
357357
#define ARM_UC_FEATURE_PAL_LINUX 0
358358
#define ARM_UC_FEATURE_PAL_RTL8195AM 1
359359

360+
#elif defined(UPDATE_CLIENT_STORAGE_PSA)
361+
#define ARM_UC_FEATURE_PAL_FLASHIAP 0
362+
#define ARM_UC_FEATURE_PAL_FLASHIAP_MCUBOOT 0
363+
#define ARM_UC_FEATURE_PAL_BLOCKDEVICE 0
364+
#define ARM_UC_FEATURE_PAL_FILESYSTEM 0
365+
#define ARM_UC_FEATURE_PAL_LINUX 0
366+
#define ARM_UC_FEATURE_PAL_RTL8195AM 0
367+
#define ARM_UC_FEATURE_PAL_PSA 1
368+
/* Disable ARM_UC_FEATURE_DELTA_PAAL which relies on ARM_UC_FEATURE_PAL_FLASHIAP */
369+
#undef ARM_UC_FEATURE_DELTA_PAAL
370+
#define ARM_UC_FEATURE_DELTA_PAAL 0
371+
360372
#else /* support legacy configuration method for storage */
361373

362374
#if defined(ARM_UC_USE_PAL_BLOCKDEVICE) && (ARM_UC_USE_PAL_BLOCKDEVICE == 1)

update-client-hub/modules/firmware-manager/source/arm_uc_firmware_manager.c

Lines changed: 80 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ static arm_uc_buffer_t *back_buffer = NULL;
4545

4646
#define UCFM_DEBUG_OUTPUT 0
4747

48+
#ifndef MBED_CONF_UPDATE_CLIENT_IN_TRANSIT_HASH_VALIDATION
49+
#define MBED_CONF_UPDATE_CLIENT_IN_TRANSIT_HASH_VALIDATION 0
50+
#endif
4851

4952
static void arm_uc_signal_ucfm_handler(uintptr_t event);
5053

@@ -124,6 +127,48 @@ static void debug_output_validation(arm_uc_hash_t *hash,
124127

125128
/******************************************************************************/
126129

130+
/* Hash comparison.
131+
*/
132+
static void arm_uc_internal_compare_hash(void)
133+
{
134+
UC_FIRM_TRACE("arm_uc_internal_compare_hash");
135+
136+
/* use specific event for "invalid hash" */
137+
uint32_t error_event = UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR;
138+
139+
/* finalize hash calculation */
140+
uint8_t hash_output_ptr[2 * UCFM_MAX_BLOCK_SIZE];
141+
arm_uc_buffer_t hash_buffer = {
142+
.size_max = sizeof(hash_output_ptr),
143+
.size = 0,
144+
.ptr = hash_output_ptr
145+
};
146+
147+
ARM_UC_cryptoHashFinish(&mdHandle, &hash_buffer);
148+
149+
/* size check before memcmp call */
150+
if (hash_buffer.size == ARM_UC_SHA256_SIZE) {
151+
int diff = memcmp(hash_buffer.ptr, package_hash, ARM_UC_SHA256_SIZE);
152+
153+
#if UCFM_DEBUG_OUTPUT
154+
debug_output_validation(package_hash, &hash_buffer);
155+
#endif
156+
157+
if (diff == 0) {
158+
/* hash matches */
159+
UC_FIRM_TRACE("image hash valid");
160+
error_event = UCFM_EVENT_FINALIZE_DONE;
161+
} else {
162+
UC_FIRM_ERR_MSG("image hash invalid");
163+
}
164+
165+
/* clear local hash */
166+
memset(package_hash, 0, ARM_UC_SHA256_SIZE);
167+
}
168+
169+
arm_uc_signal_ucfm_handler(error_event);
170+
}
171+
127172
/* Hash calculation is performed using the output buffer. This function fills
128173
the output buffer with data from the PAL.
129174
*/
@@ -132,7 +177,6 @@ static void arm_uc_internal_process_hash(void)
132177
bool double_buffering = (front_buffer != back_buffer);
133178
bool needs_more_data = (package_offset < package_configuration->package_size);
134179
arm_uc_error_t status = { .code = ERR_NONE };
135-
uint32_t error_event = UCFM_EVENT_FINALIZE_ERROR;
136180

137181
if (double_buffering && needs_more_data) {
138182
#if UCFM_DEBUG_OUTPUT
@@ -175,45 +219,11 @@ static void arm_uc_internal_process_hash(void)
175219
back_buffer);
176220
}
177221
} else {
178-
/* invert status code so that it has to be set explicitly for success */
179-
status.code = FIRM_ERR_INVALID_PARAMETER;
180-
181-
/* finalize hash calculation */
182-
uint8_t hash_output_ptr[2 * UCFM_MAX_BLOCK_SIZE];
183-
arm_uc_buffer_t hash_buffer = {
184-
.size_max = sizeof(hash_output_ptr),
185-
.size = 0,
186-
.ptr = hash_output_ptr
187-
};
188-
189-
ARM_UC_cryptoHashFinish(&mdHandle, &hash_buffer);
190-
191-
/* size check before memcmp call */
192-
if (hash_buffer.size == ARM_UC_SHA256_SIZE) {
193-
int diff = memcmp(hash_buffer.ptr,
194-
package_hash,
195-
ARM_UC_SHA256_SIZE);
196-
197-
#if UCFM_DEBUG_OUTPUT
198-
debug_output_validation(package_hash,
199-
&hash_buffer);
200-
#endif
201-
202-
/* hash matches */
203-
if (diff == 0) {
204-
UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_DONE");
205-
206-
arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_DONE);
207-
status.code = ERR_NONE;
208-
} else {
209-
/* use specific event for "invalid hash" */
210-
UC_FIRM_ERR_MSG("Invalid image hash");
211-
212-
error_event = UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR;
213-
}
214-
// clear local hash
215-
memset(package_hash, 0, ARM_UC_SHA256_SIZE);
216-
}
222+
/* All data has been passed through hash calculation.
223+
* Compare hash with manifest. This function will signal
224+
* success/failure by itself.
225+
*/
226+
arm_uc_internal_compare_hash();
217227
}
218228

219229
/* Front buffer is processed, back buffer might be reading more data.
@@ -227,7 +237,7 @@ static void arm_uc_internal_process_hash(void)
227237
/* signal error if status is not clean */
228238
if (status.error != ERR_NONE) {
229239
UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_ERROR");
230-
arm_uc_signal_ucfm_handler(error_event);
240+
arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_ERROR);
231241
}
232242
}
233243

@@ -239,28 +249,37 @@ static void event_handler_finalize(void)
239249
{
240250
UC_FIRM_TRACE("event_handler_finalize");
241251

242-
/* setup mandatory hash */
243-
arm_uc_mdType_t mdtype = ARM_UC_CU_SHA256;
244-
arm_uc_error_t result = ARM_UC_cryptoHashSetup(&mdHandle, mdtype);
252+
/* Hash is calculated while in transit */
253+
#if MBED_CONF_UPDATE_CLIENT_IN_TRANSIT_HASH_VALIDATION
254+
UC_FIRM_TRACE("calculate hash in transit");
245255

246-
if (result.error == ERR_NONE) {
247-
/* initiate hash calculation */
248-
package_offset = 0;
256+
/* All data has been passed through hash calculation.
257+
* Compare hash with manifest. This function will signal
258+
* success/failure by itself.
259+
*/
260+
arm_uc_internal_compare_hash();
249261

250-
/* indicate number of bytes needed */
251-
front_buffer->size = (package_configuration->package_size < front_buffer->size_max) ?
252-
package_configuration->package_size : front_buffer->size_max;
262+
/* Hash is calculated by reading back payload from storage*/
263+
#else
264+
UC_FIRM_TRACE("calculate hash from storage");
253265

254-
/* initiate read from PAL */
255-
result = ARM_UCP_Read(package_configuration->package_id,
256-
package_offset,
257-
front_buffer);
258-
}
266+
/* initiate hash calculation */
267+
package_offset = 0;
268+
269+
/* indicate number of bytes needed */
270+
front_buffer->size = (package_configuration->package_size < front_buffer->size_max) ?
271+
package_configuration->package_size : front_buffer->size_max;
272+
273+
/* initiate read from PAL */
274+
arm_uc_error_t result = ARM_UCP_Read(package_configuration->package_id,
275+
package_offset,
276+
front_buffer);
259277

260278
if (result.error != ERR_NONE) {
261-
UC_FIRM_ERR_MSG("ARM_UC_cryptoHashSetup failed");
279+
UC_FIRM_ERR_MSG("ARM_UCP_Read during hash check failed");
262280
arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_ERROR);
263281
}
282+
#endif
264283
}
265284

266285
/* Function for decoupling PAL callbacks using the internal task queue. */
@@ -416,13 +435,12 @@ static arm_uc_error_t ARM_UCFM_Prepare(ARM_UCFM_Setup_t *configuration,
416435
arm_uc_signal_ucfm_handler(UCFM_EVENT_PREPARE_ERROR);
417436
}
418437
}
419-
#if UCFM_DEBUG_OUTPUT
438+
420439
/* Initialize hash to calculate downloaded fragments hash */
421440
if (result.error == ERR_NONE) {
422441
arm_uc_mdType_t mdtype = ARM_UC_CU_SHA256;
423442
result = ARM_UC_cryptoHashSetup(&mdHandle, mdtype);
424443
}
425-
#endif
426444

427445
return result;
428446
}
@@ -478,8 +496,8 @@ static arm_uc_error_t ARM_UCFM_Write(const arm_uc_buffer_t *fragment)
478496
fragment_offset += length_update;
479497
}
480498
}
481-
#if UCFM_DEBUG_OUTPUT
482-
/* calculate hash on the fly for debugging purpose */
499+
#if MBED_CONF_UPDATE_CLIENT_IN_TRANSIT_HASH_VALIDATION
500+
/* calculate hash on the fly */
483501
ARM_UC_cryptoHashUpdate(&mdHandle, fragment);
484502
#endif
485503
/* store fragment using PAL */
@@ -514,7 +532,7 @@ static arm_uc_error_t ARM_UCFM_ReadFromSlot(const arm_uc_buffer_t* output, uint3
514532
return result;
515533
}
516534

517-
static arm_uc_error_t ARM_UCFM_Read(arm_uc_buffer_t *buf, uint32_t offset)
535+
static arm_uc_error_t ARM_UCFM_Read(const arm_uc_buffer_t *buf, uint32_t offset)
518536
{
519537
arm_uc_error_t result = (arm_uc_error_t) { FIRM_ERR_UNINITIALIZED };
520538
result = ARM_UCFM_ReadFromSlot(buf, package_configuration->package_id, offset);
@@ -523,7 +541,7 @@ static arm_uc_error_t ARM_UCFM_Read(arm_uc_buffer_t *buf, uint32_t offset)
523541

524542
static arm_uc_error_t ARM_UCFM_Finalize(arm_uc_buffer_t *front, arm_uc_buffer_t *back)
525543
{
526-
UC_FIRM_TRACE("ARM_UCFM_Finish");
544+
UC_FIRM_TRACE("ARM_UCFM_Finalize");
527545

528546
arm_uc_error_t result = (arm_uc_error_t) { ERR_NONE };
529547

@@ -550,20 +568,6 @@ static arm_uc_error_t ARM_UCFM_Finalize(arm_uc_buffer_t *front, arm_uc_buffer_t
550568

551569
/* disable module until next setup call is received */
552570
ready_to_receive = false;
553-
554-
#if UCFM_DEBUG_OUTPUT
555-
/* finalize hash calculation */
556-
uint8_t hash_output_ptr[2 * UCFM_MAX_BLOCK_SIZE];
557-
arm_uc_buffer_t hash_buffer = {
558-
.size_max = sizeof(hash_output_ptr),
559-
.size = 0,
560-
.ptr = hash_output_ptr
561-
};
562-
563-
ARM_UC_cryptoHashFinish(&mdHandle, &hash_buffer);
564-
565-
debug_print_hash("downloaded hash:", hash_buffer.ptr, hash_buffer.size);
566-
#endif
567571
}
568572

569573
return result;

0 commit comments

Comments
 (0)