Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
arm_uc_firmware_manager.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 #include "update-client-firmware-manager/arm_uc_firmware_manager.h" 00020 #include "update-client-common/arm_uc_common.h" 00021 00022 #include "update-client-paal/arm_uc_paal_update.h" 00023 00024 #include <stdio.h> 00025 #include <stdbool.h> 00026 00027 static ARM_UCFM_SignalEvent_t ucfm_handler = NULL; 00028 00029 static ARM_UCFM_Setup_t* package_configuration = NULL; 00030 static uint32_t package_offset = 0; 00031 static bool ready_to_receive = false; 00032 00033 static arm_uc_callback_t arm_uc_event_handler_callback = { 0 }; 00034 00035 static arm_uc_mdHandle_t mdHandle = { 0 }; 00036 static arm_uc_cipherHandle_t cipherHandle = { 0 }; 00037 static arm_uc_buffer_t* front_buffer = NULL; 00038 static arm_uc_buffer_t* back_buffer = NULL; 00039 00040 #define UCFM_DEBUG_OUTPUT 0 00041 00042 00043 static void arm_uc_signal_ucfm_handler(uint32_t event); 00044 00045 /******************************************************************************/ 00046 /* Debug output functions for writing formatted output */ 00047 /******************************************************************************/ 00048 00049 #if UCFM_DEBUG_OUTPUT 00050 00051 static void debug_output_decryption(const uint8_t* encrypted, 00052 arm_uc_buffer_t* decrypted) 00053 { 00054 for (size_t index = 0; index < UCFM_MAX_BLOCK_SIZE; index++) 00055 { 00056 if (index < decrypted->size) 00057 { 00058 uint8_t symbol = encrypted[index]; 00059 00060 printf("%02X", symbol); 00061 } 00062 else 00063 { 00064 printf(" "); 00065 } 00066 } 00067 00068 printf("\t:\t"); 00069 00070 for (size_t index = 0; index < UCFM_MAX_BLOCK_SIZE; index++) 00071 { 00072 if (index < decrypted->size) 00073 { 00074 uint8_t symbol = encrypted[index]; 00075 00076 if ((symbol > 32) && (symbol < 127)) 00077 { 00078 printf("%c", symbol); 00079 } 00080 else 00081 { 00082 printf(" "); 00083 } 00084 } 00085 else 00086 { 00087 printf(" "); 00088 } 00089 } 00090 00091 printf("\t:\t"); 00092 00093 for (size_t index = 0; index < decrypted->size_max; index++) 00094 { 00095 if (index < decrypted->size) 00096 { 00097 uint8_t symbol = decrypted->ptr[index]; 00098 00099 if ((symbol > 32) && (symbol < 127)) 00100 { 00101 printf("%c", symbol); 00102 } 00103 else 00104 { 00105 printf(" "); 00106 } 00107 } 00108 else 00109 { 00110 printf(" "); 00111 } 00112 } 00113 00114 printf("\r\n"); 00115 } 00116 00117 static void debug_output_validation(arm_uc_buffer_t* hash, 00118 arm_uc_buffer_t* output_buffer) 00119 { 00120 printf("\r\n"); 00121 printf("expected hash : "); 00122 for (size_t index = 0; index < hash->size; index++) 00123 { 00124 printf("%02X", hash->ptr[index]); 00125 } 00126 printf("\r\n"); 00127 00128 printf("calculated hash: "); 00129 for (size_t index = 0; index < output_buffer->size; index++) 00130 { 00131 printf("%02X", output_buffer->ptr[index]); 00132 } 00133 printf("\r\n"); 00134 printf("\r\n"); 00135 } 00136 00137 #endif 00138 00139 /******************************************************************************/ 00140 00141 /* Hash calculation is performed using the output buffer. This function fills 00142 the output buffer with data from the PAL. 00143 */ 00144 static void arm_uc_internal_process_hash(void) 00145 { 00146 bool double_buffering = (front_buffer != back_buffer); 00147 bool needs_more_data = (package_offset < package_configuration->package_size); 00148 arm_uc_error_t status = { .code = ERR_NONE }; 00149 uint32_t error_event = UCFM_EVENT_FINALIZE_ERROR; 00150 00151 if (double_buffering && needs_more_data) 00152 { 00153 #if UCFM_DEBUG_OUTPUT 00154 printf("double buffering: %p %" PRIX32 "\r\n", back_buffer, back_buffer->size_max); 00155 #endif 00156 00157 /* if using double buffering, initiate a new data read as soon as possible */ 00158 /* Indicate read size */ 00159 uint32_t bytes_remaining = package_configuration->package_size - package_offset; 00160 back_buffer->size = (bytes_remaining > back_buffer->size_max)? 00161 back_buffer->size_max : bytes_remaining; 00162 00163 /* initiate read from PAL */ 00164 status = ARM_UCP_Read(package_configuration->package_id, 00165 package_offset, 00166 back_buffer); 00167 } 00168 00169 if (status.error == ERR_NONE) 00170 { 00171 /* process data in front buffer */ 00172 ARM_UC_cryptoHashUpdate(&mdHandle, front_buffer); 00173 00174 if (needs_more_data) 00175 { 00176 /* if we're actually using two buffers, the read operation was initiated earlier, 00177 * otherwise it needs to be initiated now, after we're done hashing the only 00178 * buffer that we're using 00179 */ 00180 if (!double_buffering) 00181 { 00182 #if UCFM_DEBUG_OUTPUT 00183 printf("single buffering: %p\r\n", front_buffer); 00184 #endif 00185 /* Indicate read size */ 00186 uint32_t bytes_remaining = package_configuration->package_size - package_offset; 00187 back_buffer->size = (bytes_remaining > back_buffer->size_max)? 00188 back_buffer->size_max : bytes_remaining; 00189 00190 /* initiate read from PAL */ 00191 status = ARM_UCP_Read(package_configuration->package_id, 00192 package_offset, 00193 back_buffer); 00194 } 00195 } 00196 else 00197 { 00198 /* invert status code so that it has to be set explicitly for success */ 00199 status.code = ERR_INVALID_PARAMETER; 00200 00201 /* finalize hash calculation */ 00202 uint8_t hash_output_ptr[2 * UCFM_MAX_BLOCK_SIZE]; 00203 arm_uc_buffer_t hash_buffer = { 00204 .size_max = sizeof(hash_output_ptr), 00205 .size = 0, 00206 .ptr = hash_output_ptr 00207 }; 00208 00209 ARM_UC_cryptoHashFinish(&mdHandle, &hash_buffer); 00210 00211 /* size check before memcmp call */ 00212 if (hash_buffer.size == package_configuration->hash->size) 00213 { 00214 int diff = memcmp(hash_buffer.ptr, 00215 package_configuration->hash->ptr, 00216 package_configuration->hash->size); 00217 00218 #if UCFM_DEBUG_OUTPUT 00219 debug_output_validation(package_configuration->hash, 00220 &hash_buffer); 00221 #endif 00222 00223 /* hash matches */ 00224 if (diff == 0) 00225 { 00226 UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_DONE"); 00227 00228 arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_DONE); 00229 status.code = ERR_NONE; 00230 } 00231 else 00232 { 00233 /* use specific event for "invalid hash" */ 00234 UC_FIRM_ERR_MSG("Invalid image hash"); 00235 00236 error_event = UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR; 00237 } 00238 } 00239 } 00240 00241 /* Front buffer is processed, back buffer might be reading more data. 00242 Swap buffer so that data will be ready in front buffer 00243 */ 00244 arm_uc_buffer_t* temp = front_buffer; 00245 front_buffer = back_buffer; 00246 back_buffer = temp; 00247 } 00248 00249 /* signal error if status is not clean */ 00250 if (status.error != ERR_NONE) 00251 { 00252 UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_ERROR"); 00253 arm_uc_signal_ucfm_handler(error_event); 00254 } 00255 } 00256 00257 /******************************************************************************/ 00258 00259 /* Function for decoupling PAL callbacks using the internal task queue. */ 00260 /* Write commit done */ 00261 static void event_handler_finalize(void) 00262 { 00263 UC_FIRM_TRACE("event_handler_finalize"); 00264 00265 /* setup mandatory hash */ 00266 arm_uc_mdType_t mdtype = ARM_UC_CU_SHA256; 00267 arm_uc_error_t result = ARM_UC_cryptoHashSetup(&mdHandle, mdtype); 00268 00269 if (result.error == ERR_NONE) 00270 { 00271 /* initiate hash calculation */ 00272 package_offset = 0; 00273 00274 /* indicate number of bytes needed */ 00275 front_buffer->size = (package_configuration->package_size < front_buffer->size_max)? 00276 package_configuration->package_size : front_buffer->size_max; 00277 00278 /* initiate read from PAL */ 00279 result = ARM_UCP_Read(package_configuration->package_id, 00280 package_offset, 00281 front_buffer); 00282 } 00283 00284 if (result.error != ERR_NONE) 00285 { 00286 UC_FIRM_ERR_MSG("ARM_UC_cryptoHashSetup failed"); 00287 arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_ERROR); 00288 } 00289 } 00290 00291 /* Function for decoupling PAL callbacks using the internal task queue. */ 00292 static void event_handler_read(void) 00293 { 00294 #if UCFM_DEBUG_OUTPUT 00295 printf("event_handler_read: %" PRIX32 "\r\n", front_buffer->size); 00296 #endif 00297 00298 /* check that read succeeded in reading data into buffer */ 00299 if (front_buffer->size > 0) 00300 { 00301 /* check if read over shot */ 00302 if ((package_offset + front_buffer->size) > 00303 package_configuration->package_size) 00304 { 00305 /* trim buffer */ 00306 front_buffer->size = package_configuration->package_size - package_offset; 00307 } 00308 00309 /* update offset and continue reading data from PAL */ 00310 package_offset += front_buffer->size; 00311 arm_uc_internal_process_hash(); 00312 } 00313 else 00314 { 00315 /* error - no data processed */ 00316 UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_ERROR"); 00317 arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_ERROR); 00318 } 00319 } 00320 00321 static void arm_uc_signal_ucfm_handler(uint32_t event) 00322 { 00323 if (ucfm_handler) 00324 { 00325 ucfm_handler(event); 00326 } 00327 } 00328 00329 static void arm_uc_internal_event_handler(uint32_t event) 00330 { 00331 switch (event) 00332 { 00333 case ARM_UC_PAAL_EVENT_FINALIZE_DONE: 00334 event_handler_finalize(); 00335 break; 00336 case ARM_UC_PAAL_EVENT_READ_DONE: 00337 event_handler_read(); 00338 break; 00339 default: 00340 /* pass all other events directly */ 00341 arm_uc_signal_ucfm_handler(event); 00342 break; 00343 } 00344 } 00345 00346 static void ARM_UCFM_PALEventHandler(uint32_t event) 00347 { 00348 /* decouple event handler from callback */ 00349 ARM_UC_PostCallback(&arm_uc_event_handler_callback, 00350 arm_uc_internal_event_handler, event); 00351 } 00352 00353 /******************************************************************************/ 00354 static arm_uc_error_t ARM_UCFM_Initialize(ARM_UCFM_SignalEvent_t handler) 00355 { 00356 UC_FIRM_TRACE("ARM_UCFM_Initialize"); 00357 00358 arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER }; 00359 00360 if (handler) 00361 { 00362 result = ARM_UCP_Initialize(ARM_UCFM_PALEventHandler); 00363 00364 if (result.error == ERR_NONE) 00365 { 00366 ucfm_handler = handler; 00367 } 00368 } 00369 00370 return result; 00371 } 00372 00373 static arm_uc_error_t ARM_UCFM_Prepare(ARM_UCFM_Setup_t* configuration, 00374 const arm_uc_firmware_details_t* details, 00375 arm_uc_buffer_t* buffer) 00376 { 00377 UC_FIRM_TRACE("ARM_UCFM_Setup"); 00378 00379 arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_NONE }; 00380 00381 /* sanity checks */ 00382 if (!ucfm_handler) 00383 { 00384 UC_FIRM_ERR_MSG("Event handler not set. Should call Initialise before calling Setup"); 00385 result = (arm_uc_error_t){ FIRM_ERR_UNINITIALIZED }; 00386 } 00387 /* check configuration is defined and contains key and iv. */ 00388 else if ((!(configuration && 00389 ((configuration->mode == UCFM_MODE_NONE_SHA_256) || 00390 (configuration->key && configuration->iv)))) || 00391 !buffer || 00392 !buffer->ptr) 00393 { 00394 result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER }; 00395 } 00396 00397 /* allocate space using PAL */ 00398 if (result.error == ERR_NONE) 00399 { 00400 result = ARM_UCP_Prepare(configuration->package_id, 00401 details, 00402 buffer); 00403 00404 if (result.error != ERR_NONE) 00405 { 00406 UC_FIRM_ERR_MSG("ARM_UCP_Prepare failed"); 00407 } 00408 } 00409 00410 /* setup encryption if requested by mode */ 00411 if ((result.error == ERR_NONE) && 00412 (configuration->mode != UCFM_MODE_NONE_SHA_256)) 00413 { 00414 /* A previously aborted firmware write will have left the cipherHandler 00415 in an inconsistent state. If the IV is not NULL, clear the context 00416 using the call to finish and set the struct to zero. 00417 */ 00418 if (cipherHandle.aes_iv != NULL) 00419 { 00420 ARM_UC_cryptoDecryptFinish(&cipherHandle, buffer); 00421 memset(&cipherHandle, 0, sizeof(arm_uc_cipherHandle_t)); 00422 } 00423 00424 /* setup cipherHanlde with decryption keys */ 00425 uint32_t bits = (configuration->mode == UCFM_MODE_AES_CTR_128_SHA_256) ? 128 : 256; 00426 result = ARM_UC_cryptoDecryptSetup(&cipherHandle, 00427 configuration->key, 00428 configuration->iv, 00429 bits); 00430 00431 if (result.error != ERR_NONE) 00432 { 00433 UC_FIRM_ERR_MSG("ARM_UC_cryptoDecryptSetup failed in %" PRIu32 " bit mode", bits); 00434 } 00435 } 00436 00437 /* Initialise the internal state */ 00438 if (result.error == ERR_NONE) 00439 { 00440 package_configuration = configuration; 00441 package_offset = 0; 00442 ready_to_receive = true; 00443 } 00444 00445 return result; 00446 } 00447 00448 static arm_uc_error_t ARM_UCFM_Write(const arm_uc_buffer_t* fragment) 00449 { 00450 UC_FIRM_TRACE("ARM_UCFM_Write"); 00451 00452 arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_NONE }; 00453 00454 if (!fragment || fragment->size_max == 0 || fragment->size > fragment->size_max || !fragment->ptr) 00455 { 00456 result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER }; 00457 } 00458 else if (!ready_to_receive) 00459 { 00460 result = (arm_uc_error_t){ FIRM_ERR_UNINITIALIZED }; 00461 } 00462 else 00463 { 00464 /* decrypt fragment before writing to PAL */ 00465 if (package_configuration->mode != UCFM_MODE_NONE_SHA_256) 00466 { 00467 /* temporary buffer for decrypting in place */ 00468 uint8_t decrypt_output_ptr[2 * UCFM_MAX_BLOCK_SIZE]; 00469 arm_uc_buffer_t decrypt_buffer = { 00470 .size_max = sizeof(decrypt_output_ptr), 00471 .size = 0, 00472 .ptr = decrypt_output_ptr 00473 }; 00474 00475 uint32_t fragment_offset = 0; 00476 while (fragment_offset < fragment->size) 00477 { 00478 /* default to max length */ 00479 uint32_t length_update = decrypt_buffer.size_max; 00480 00481 /* adjust size to not overshoot */ 00482 if (fragment_offset + length_update > fragment->size) 00483 { 00484 length_update = fragment->size - fragment_offset; 00485 } 00486 00487 /* decrypt part of the fragment using the offset */ 00488 ARM_UC_cryptoDecryptUpdate(&cipherHandle, 00489 &fragment->ptr[fragment_offset], 00490 length_update, 00491 &decrypt_buffer); 00492 00493 #if UCFM_DEBUG_OUTPUT 00494 debug_output_decryption(&fragment->ptr[fragment_offset], 00495 &decrypt_buffer); 00496 #endif 00497 00498 /* overwrite the encrypted data with the decrypted data */ 00499 memcpy(&fragment->ptr[fragment_offset], 00500 decrypt_buffer.ptr, 00501 length_update); 00502 00503 /* update offset */ 00504 fragment_offset += length_update; 00505 } 00506 } 00507 00508 /* store fragment using PAL */ 00509 result = ARM_UCP_Write(package_configuration->package_id, 00510 package_offset, 00511 fragment); 00512 00513 if (result.error == ERR_NONE) 00514 { 00515 package_offset += fragment->size; 00516 } 00517 } 00518 00519 return result; 00520 } 00521 00522 static arm_uc_error_t ARM_UCFM_Finalize(arm_uc_buffer_t* front, arm_uc_buffer_t* back) 00523 { 00524 UC_FIRM_TRACE("ARM_UCFM_Finish"); 00525 00526 arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_NONE }; 00527 00528 if (!ready_to_receive) 00529 { 00530 result = (arm_uc_error_t){ FIRM_ERR_UNINITIALIZED }; 00531 } 00532 else if ((front == NULL) || 00533 (front != NULL && ((front->size_max % ARM_UC_SHA256_SIZE) != 0)) || 00534 (back != NULL && ((back->size_max % ARM_UC_SHA256_SIZE) != 0))) 00535 { 00536 result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER }; 00537 } 00538 else 00539 { 00540 /* flush decryption buffer, discard data */ 00541 ARM_UC_cryptoDecryptFinish(&cipherHandle, front); 00542 memset(&cipherHandle, 0, sizeof(arm_uc_cipherHandle_t)); 00543 00544 /* save buffers, checking if the buffers actually exist */ 00545 front_buffer = front; 00546 back_buffer = (back == NULL) ? front_buffer : back; 00547 00548 /* flush to PAL */ 00549 result = ARM_UCP_Finalize(package_configuration->package_id); 00550 00551 /* disable module until next setup call is received */ 00552 ready_to_receive = false; 00553 } 00554 00555 return result; 00556 } 00557 00558 static arm_uc_error_t ARM_UCFM_Activate(uint32_t location) 00559 { 00560 UC_FIRM_TRACE("ARM_UCFM_Activate"); 00561 00562 arm_uc_error_t result = { .code = FIRM_ERR_ACTIVATE }; 00563 00564 if (ucfm_handler) 00565 { 00566 result = ARM_UCP_Activate(location); 00567 } 00568 00569 return result; 00570 } 00571 00572 static arm_uc_error_t ARM_UCFM_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details) 00573 { 00574 UC_FIRM_TRACE("ARM_UCFM_GetActiveFirmwareDetails"); 00575 00576 arm_uc_error_t result = { .code = FIRM_ERR_INVALID_PARAMETER }; 00577 00578 if (ucfm_handler && details) 00579 { 00580 result = ARM_UCP_GetActiveFirmwareDetails(details); 00581 } 00582 00583 return result; 00584 } 00585 00586 static arm_uc_error_t ARM_UCFM_GetFirmwareDetails(uint32_t location, 00587 arm_uc_firmware_details_t* details) 00588 { 00589 UC_FIRM_TRACE("ARM_UCFM_GetFirmwareDetails"); 00590 00591 arm_uc_error_t result = { .code = FIRM_ERR_INVALID_PARAMETER }; 00592 00593 if (ucfm_handler && details) 00594 { 00595 result = ARM_UCP_GetFirmwareDetails(location, details); 00596 } 00597 00598 return result; 00599 } 00600 00601 static arm_uc_error_t ARM_UCFM_GetInstallerDetails(arm_uc_installer_details_t* details) 00602 { 00603 UC_FIRM_TRACE("ARM_UCFM_GetInstallerDetails"); 00604 00605 arm_uc_error_t result = { .code = FIRM_ERR_INVALID_PARAMETER }; 00606 00607 if (ucfm_handler && details) 00608 { 00609 result = ARM_UCP_GetInstallerDetails(details); 00610 } 00611 00612 return result; 00613 } 00614 00615 ARM_UC_FIRMWARE_MANAGER_t ARM_UC_FirmwareManager = { 00616 .Initialize = ARM_UCFM_Initialize, 00617 .Prepare = ARM_UCFM_Prepare, 00618 .Write = ARM_UCFM_Write, 00619 .Finalize = ARM_UCFM_Finalize, 00620 .Activate = ARM_UCFM_Activate, 00621 .GetActiveFirmwareDetails = ARM_UCFM_GetActiveFirmwareDetails, 00622 .GetFirmwareDetails = ARM_UCFM_GetFirmwareDetails, 00623 .GetInstallerDetails = ARM_UCFM_GetInstallerDetails 00624 };
Generated on Tue Jul 12 2022 19:12:11 by 1.7.2