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