Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-cloud-workshop-connect-HTS221 by
arm_uc_mmInsertManifest.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 "arm_uc_mmCryptoUtils.h" 00020 #include "arm_uc_mmCommon.h" 00021 #include "arm_uc_mmConfig.h" 00022 #include "arm_uc_mmStateSelector.h" 00023 #include "arm_uc_mmDerManifestAccessors.h" 00024 #include "arm_uc_mmDerManifestParser.h" 00025 #include "arm_uc_mmGetLatestTimestamp.h" 00026 #include "arm_uc_mmFSMHelper.h" 00027 #include "arm_uc_mmInsertManifest.h" 00028 #include "update-client-common/arm_uc_scheduler.h" 00029 00030 #include "update-client-manifest-manager/update-client-manifest-manager-context.h" 00031 #include "update-client-manifest-manager/update-client-manifest-manager.h" 00032 #include "update-client-manifest-manager/update-client-manifest-types.h" 00033 00034 #include "pal4life-device-identity/pal_device_identity.h" 00035 #include "pal.h" 00036 00037 #include <stdint.h> 00038 #include <stdio.h> 00039 #include <stddef.h> 00040 #include <string.h> 00041 00042 /** 00043 * @file arm_uc_mmInsertManifest.c 00044 * @brief Inserts a manifest into a slot specified by the manifest. 00045 * @details This API is used by the manifest manager to validate and store a manifest. 00046 * 00047 * The workflow for inserting a manifest is: 00048 * 1. Check the version of the manifest 00049 * 2. Validate the cryptographic mode 00050 * 3. Verify the hash of the manifest. 00051 * 4. Verify each signature of the manifest. 00052 * 5. Validate the applicability of the manifest (GUID matching) 00053 * 6. Validate the storage identifier 00054 * TBD: Store the manifest in the KCM 00055 * 00056 * NOTE: There is a security vs. energy tradeoff in this code. 00057 * To optimize for energy, the cheapest fields should be checked first, that means checking applicability before 00058 * hash or signature. However, to optimize for security, we must prioritize safety over energy. Since parsers are 00059 * notorious sources of bugs, we must make every effort to protect the parser from insecure content. This means 00060 * accessing the absolute minimum of fields prior to verifyinng the signature. 00061 * 00062 * The current version of this code optimizes for security. Once the parser has been more thoroughly validated, we can 00063 * consider exposing it to more unvalidated data as an energy saving measure. 00064 * 00065 * @dot 00066 * digraph { 00067 * Idle 00068 * Idle -> Begin [label="[event == BEGIN]"] 00069 * Begin 00070 * Begin -> VerifyBasicParameters 00071 * VerifyBasicParameters 00072 * // Validate the manifest size (This is a precursor to security validation) 00073 * // Validate the manifest version (This is required in order to know how to parse the manifest) 00074 * // Validate the manifest encryption mode (This is required in order to know how to validate the signature) 00075 * VerifyBasicParameters -> VerifyHash 00076 * VerifyBasicParameters -> VerifyFail [label="[Basic Parameters invalid]"] 00077 * VerifyHash 00078 * VerifyHash -> VerifySignatureLoopStart 00079 * VerifyHash -> VerifyFail [label="[Hash invalid]"] 00080 * VerifySignatureLoopStart 00081 * VerifySignatureLoopStart -> VerifySignatureStart 00082 * VerifySignatureStart 00083 * VerifySignatureStart -> VerifySignature 00084 * VerifySignatureStart -> VerifyParameters [label="[No More Signatures]"] 00085 * VerifySignature 00086 * VerifySignature -> VerifyParameters [label="[Last Signature]"] 00087 * VerifySignature -> VerifyFail [label="[Signature invalid]"] 00088 * // Validate the applicability of the manifest (GUID matching) 00089 * // Validate the storage identifier 00090 * VerifyParameters 00091 * VerifyParameters -> VerifyTimestamp 00092 * VerifyParameters -> VerifyFail [label="[Parameters invalid]"] 00093 * VerifyTimestampStart 00094 * VerifyTimestampStart -> VerifyTimestamp 00095 * VerifyTimestamp 00096 * VerifyTimestamp -> VerifyApplication 00097 * VerifyTimestamp -> VerifyFail [label="[Timestamp too old]"] 00098 * VerifyApplication 00099 * VerifyApplication -> VerifyDone 00100 * VerifyApplication -> VerifyFail [label="[App denied]"] 00101 * VerifyFail 00102 * VerifyFail -> Idle 00103 * VerifyDone 00104 * VerifyDone -> AlertHub 00105 * AlertHub 00106 * AlertHub -> Idle 00107 * } 00108 * @enddot 00109 */ 00110 00111 #if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE 00112 static const char* ARM_UC_mmInsertState2Str(uint32_t state) 00113 { 00114 switch (state) { 00115 #define ENUM_AUTO(name) case name: return #name; 00116 #define ENUM_FIXED(name, val) ENUM_AUTO(name) 00117 ARM_UC_MM_INS_STATE_LIST 00118 #undef ENUM_AUTO 00119 #undef ENUM_FIXED 00120 default: 00121 return "Unknown State"; 00122 } 00123 } 00124 #endif 00125 00126 #define max(A,B) ((A)>(B)?(A):(B)) 00127 00128 /** @brief Validate that the resource contained in this signed container is a manifest. 00129 */ 00130 static arm_uc_error_t validateResourceType(arm_uc_buffer_t* buffer) 00131 { 00132 arm_uc_error_t err = {MFST_ERR_NONE}; 00133 arm_uc_buffer_t type = { 0 }; 00134 // Read the resource type field. 00135 err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, 00136 ARM_UC_MM_DER_RESOURCE_TYPE, &type); 00137 if (type.ptr == NULL) 00138 { 00139 err.code = MFST_ERR_DER_FORMAT; 00140 } 00141 else if (err.error == ERR_NONE) 00142 { 00143 // The resource type must be a manifest. 00144 if (ARM_UC_mmDerBuf2Uint(&type) != 0) 00145 { 00146 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_DER_FORMAT); 00147 } 00148 } 00149 return err; 00150 } 00151 /** @brief Validate that this manifest is a supported version 00152 */ 00153 static arm_uc_error_t validateManifestVersion(arm_uc_buffer_t* buffer) 00154 { 00155 uint32_t val = 0; 00156 // Read the manifest version 00157 arm_uc_error_t err = ARM_UC_mmGetVersion(buffer, &val); 00158 if (err.code == MFST_ERR_NONE) 00159 { 00160 // Verify the manifest version 00161 if (val != MANIFEST_SUPPORTED_VERSION) { 00162 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_VERSION); 00163 } 00164 } 00165 return err; 00166 } 00167 00168 /** @brief Validate the manifest size 00169 */ 00170 static arm_uc_error_t validateManifestSize(arm_uc_buffer_t* buffer) 00171 { 00172 arm_uc_error_t err = {MFST_ERR_NONE}; 00173 arm_uc_buffer_t val = {0}; 00174 00175 // Get the manifest inner part 00176 err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_MFST, &val); 00177 if (err.error == ERR_NONE) 00178 { 00179 // Make sure that the manifest does not overrun. 00180 uintptr_t bufend = (uintptr_t)buffer->ptr + buffer->size; 00181 uintptr_t valend = (uintptr_t)val.ptr + val.size; 00182 if (bufend < valend) 00183 { 00184 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_SIZE); 00185 } 00186 // TODO: There should be a minimum size for the manifest too. 00187 } 00188 return err; 00189 } 00190 00191 /** @brief Validate the crypto mode 00192 * @details The manifest must contain a cryptographic mode identifier. Only a small number of modes are supported. If 00193 * the manifest is to be processed, then one of these modes must be supported. 00194 * 00195 * While the manifest format supports OID cryptographic mode identifiers, these are not currently supported in 00196 * the update client. 00197 */ 00198 static arm_uc_error_t validateCryptoMode(arm_uc_buffer_t* buffer, arm_uc_mm_crypto_flags_t* flags) 00199 { 00200 uint32_t cryptoMode = 1U; // default SHA256 and ECC 00201 arm_uc_error_t err = ARM_UC_mmGetCryptoMode(buffer, &cryptoMode); 00202 if (err.error == ERR_NONE) 00203 { 00204 if (cryptoMode <= MFST_CRYPT_UNINIT || MFST_CRYPT_MAX <= cryptoMode) 00205 { 00206 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_CRYPTO_MODE); 00207 } 00208 else 00209 { 00210 *flags = ARM_UC_mmGetCryptoFlags(cryptoMode); 00211 } 00212 } 00213 return err; 00214 } 00215 00216 // Validate that the manifest applies to this device 00217 static arm_uc_error_t validateFirmwareApplicability(arm_uc_buffer_t* buffer) 00218 { 00219 arm_uc_buffer_t vendor_guid = {0}; 00220 arm_uc_buffer_t class_guid = {0}; 00221 arm_uc_buffer_t device_guid = {0}; 00222 00223 arm_uc_error_t err = {MFST_ERR_NONE}; 00224 if (err.code == MFST_ERR_NONE) 00225 err = ARM_UC_mmGetVendorGuid(buffer, &vendor_guid); 00226 if (err.code == MFST_ERR_NONE) 00227 err = ARM_UC_mmGetClassGuid(buffer, &class_guid); 00228 if (err.code == MFST_ERR_NONE) 00229 err = ARM_UC_mmGetDeviceGuid(buffer, &device_guid); 00230 if (err.code == MFST_ERR_NONE) 00231 err = pal_deviceIdentityCheck( 00232 (vendor_guid.size != 0UL ? &vendor_guid : NULL), 00233 (class_guid.size != 0UL ? &class_guid : NULL), 00234 (device_guid.size != 0UL ? &device_guid : NULL) 00235 ); 00236 return err; 00237 } 00238 /* 00239 * DOT Setup 00240 * DOT: digraph { 00241 */ 00242 00243 /* @brief Idle state 00244 * @details The idle state generates no events and causes no state transitions. It only moves to a new state when the 00245 * `ARM_UC_MM_EVENT_BEGIN` event is received. 00246 * DOT States: 00247 * DOT: Idle 00248 * DOT: Idle -> Begin [label="[event == BEGIN]"] 00249 */ 00250 static arm_uc_error_t state_idle(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00251 { 00252 arm_uc_error_t err = {MFST_ERR_NONE}; 00253 if (*event == ARM_UC_MM_EVENT_BEGIN) 00254 { 00255 ctx->state = ARM_UC_MM_INS_STATE_BEGIN; 00256 } 00257 return err; 00258 } 00259 /* @brief Begin state 00260 * @details This is an empty placeholder state that is used as a state transition target for Idle. This allows 00261 * modifications to the FSM flow without modifying Idle. 00262 * DOT States: 00263 * DOT: Begin 00264 * DOT: Begin -> VerifyBasicParameters 00265 */ 00266 static arm_uc_error_t state_begin(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00267 { 00268 arm_uc_error_t err = {MFST_ERR_NONE}; 00269 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_BASIC_PARAMS; 00270 return err; 00271 } 00272 /* @brief Verify critical pre-security parameters 00273 * @details Some parameters must be verified before security validation. These parameters are critical to either finding 00274 * or validating the security parameters themselves. The parameters validated are: 00275 * 00276 * * The resource size (This is a precursor to security validation) 00277 * * The resource is a manifest (A non-manifest will not be accepted) 00278 * * The manifest version (This is required in order to know how to parse the manifest) 00279 * * The manifest encryption mode (This is required in order to know how to validate the signature) 00280 * 00281 * DOT States: 00282 * DOT: VerifyBasicParameters 00283 * DOT: VerifyBasicParameters -> VerifyHash 00284 * DOT: VerifyBasicParameters -> VerifyFail [label="[Basic Parameters invalid]"] 00285 */ 00286 static arm_uc_error_t state_verifyBasicParameters(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00287 { 00288 arm_uc_error_t err = {MFST_ERR_NONE}; 00289 00290 if (err.error == ERR_NONE) 00291 { 00292 err = validateResourceType(&ctx->manifest); 00293 } 00294 if (err.error == ERR_NONE) 00295 { 00296 err = validateManifestSize(&ctx->manifest); 00297 } 00298 if (err.error == ERR_NONE) 00299 { 00300 err = validateManifestVersion(&ctx->manifest); 00301 } 00302 if (err.error == ERR_NONE) 00303 { 00304 err = validateCryptoMode(&ctx->manifest, &ctx->cryptoMode); 00305 } 00306 // Set the state based on error condition 00307 if (err.error == ERR_NONE) 00308 { 00309 ctx->state = ARM_UC_MM_INS_STATE_HASH_VERIFY; 00310 } 00311 else 00312 { 00313 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL; 00314 } 00315 return err; 00316 } 00317 /** @brief Verify the manifest hash 00318 * @details Manifest hash verification happens in a single state. This is because hash verification is currently 00319 * considered to be a blocking operation. If an asynchronous hash accelerator is used, this will need to be 00320 * modified to use two states to handle hash initiation and waiting for completion. 00321 * 00322 * DOT States: 00323 * DOT: VerifyHash 00324 * DOT: VerifyHash -> VerifySignatureLoopStart 00325 * DOT: VerifyHash -> VerifyFail [label="[Hash invalid]"] 00326 */ 00327 static arm_uc_error_t state_verifyHash(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00328 { 00329 arm_uc_error_t err = ARM_UC_mmValidateManifestHash(&ctx->manifest); 00330 if (err.error == ERR_NONE) 00331 { 00332 // If the cryptoMode specifies either ecc or rsa, then we can validate that. 00333 if(ctx->cryptoMode.ecc || ctx->cryptoMode.rsa) 00334 { 00335 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_LOOP; 00336 } 00337 else 00338 { 00339 // Unsigned manifests are not supported at this time, so they count as a failure. 00340 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_INVALID_SIGNATURE); 00341 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL; 00342 } 00343 } 00344 else 00345 { 00346 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_HASH); 00347 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL; 00348 } 00349 return err; 00350 } 00351 /** @brief Start the signature verification loop. 00352 * @details This state provides initialization for the signature verification loop. 00353 * The outer loop is tracked by `loopCounters[0]` and represents the signature index. 00354 * 00355 * DOT States: 00356 * DOT: VerifySignatureLoopStart 00357 * DOT: VerifySignatureLoopStart -> VerifySignatureStart 00358 */ 00359 static arm_uc_error_t state_verifySignatureLoopStart(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00360 { 00361 arm_uc_error_t err = {MFST_ERR_NONE}; 00362 // Set the exterior loop counter 00363 ctx->loopCounters[0] = 0; 00364 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_START; 00365 return err; 00366 } 00367 /** @brief Begin verifying the signature. 00368 * @details This calls the ARM_UC_mmValidateSignature setup function, but does not start the signature verification 00369 * state machine. `ARM_UC_mmValidateSignature` attempts to read a signature at the index specified by the 00370 * outer loop counter (`loopCounters[0]`). If it fails, it assumes that all signatures have been processed. 00371 * If at least one signature has been processed, then continue with validation, but a minimum of one signature 00372 * is required for validation. 00373 * 00374 * DOT States: 00375 * DOT: VerifySignatureStart 00376 * DOT: VerifySignatureStart -> VerifySignature 00377 * DOT: VerifySignatureStart -> VerifyParameters [label="[No More Signatures]"] 00378 */ 00379 static arm_uc_error_t state_verifySignatureStart(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00380 { 00381 // start the signature verification 00382 arm_uc_error_t err = ARM_UC_mmValidateSignature(&ctx->signatureContext, 00383 ARM_UC_mmCallbackFSMEntry, 00384 &ctx->manifest, 00385 &ctx->certificateStorage, 00386 ctx->loopCounters[0]); 00387 if (err.error == ERR_NONE) 00388 { 00389 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_WAIT; 00390 *event = ARM_UC_MM_RC_NONE; 00391 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_PENDING); 00392 } 00393 // If there are no more signatures and at least one signature was validated 00394 if (err.code == ARM_UC_DP_ERR_NO_MORE_ELEMENTS) 00395 { 00396 if (ctx->loopCounters[0] >= 1) 00397 { 00398 // Signature validation done. Move on to parameter validation. 00399 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_PARAMS; 00400 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_NONE); 00401 } 00402 else 00403 { 00404 // WARNING: If the fingerprint is empty, MFST_ERR_INVALID_SIGNATURE is returned. 00405 // At least one signature is required. 00406 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_INVALID_SIGNATURE); 00407 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL; 00408 } 00409 } 00410 return err; 00411 } 00412 /** @brief Wait for signature validation to complete. 00413 * @details Calls the `ARM_UC_mmValidateSignature` state machine and collects exit status. When signature validation is 00414 * complete, the return value will be `MFST_ERR_NONE`. 00415 * 00416 * DOT States: 00417 * DOT: VerifySignature 00418 * DOT: VerifySignature -> VerifyFail [label="[Signature invalid]"] 00419 * DOT: VerifySignature -> VerifySignatureStart 00420 */ 00421 static arm_uc_error_t state_verifySignature(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00422 { 00423 arm_uc_error_t err = {MFST_ERR_NONE}; 00424 // Wait for the signature verification to end. 00425 // If the signature validation ended 00426 if (*event == ARM_UC_MM_RC_DONE) 00427 { 00428 // Increment the loop counter 00429 ctx->loopCounters[0] += 1; 00430 // Return to the beginning of the loop. 00431 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_START; 00432 } 00433 else if (*event == ARM_UC_MM_RC_ERROR) 00434 { 00435 err = ctx->signatureContext.storedError; 00436 } 00437 else 00438 { 00439 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_BAD_EVENT); 00440 } 00441 return err; 00442 } 00443 /** @brief Validates remaining parsable parameters 00444 * @details This currently means only the firmware applicability, as identified by UUID. Several additiional parameters 00445 * could be validated: 00446 * 00447 * * Storage identifier 00448 * * Payload type identifier 00449 * * URI validation in payload reference 00450 * * Valid size of payload hash 00451 * * nonce size, non-zero 00452 * * Valid From, Valid To 00453 * * timestamp 00454 * * Encryption info 00455 * 00456 * 00457 * DOT States: 00458 * DOT: VerifyParameters 00459 * DOT: VerifyParameters -> VerifyApplication 00460 * DOT: VerifyParameters -> VerifyFail [label="[Parameters invalid]"] 00461 */ 00462 static arm_uc_error_t state_verifyParameters(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00463 { 00464 arm_uc_error_t err = validateFirmwareApplicability(&ctx->manifest); 00465 if (err.error == ERR_NONE) 00466 { 00467 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_TS_START; 00468 } 00469 return err; 00470 } 00471 /** @brief Initiate timestamp verification. 00472 * @details This starts the process of loading the active timestamp. This may be a non-blocking operation. 00473 * 00474 * DOT States: 00475 * DOT: VerifyTimestampStart 00476 * DOT: VerifyTimestampStart -> VerifyTimestamp 00477 */ 00478 static arm_uc_error_t state_verifyTimestampStart(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00479 { 00480 // Since this is a root manifest, extract maximum stored timestamp 00481 arm_uc_error_t err = getLatestManifestTimestamp(&ctx->max_ts, NULL); 00482 if (err.error == ERR_NONE) 00483 { 00484 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_TS; 00485 *event = ARM_UC_MM_EVENT_BEGIN; 00486 } 00487 return err; 00488 } 00489 /** @brief Waits for the active timestamp to be loaded. 00490 * @details Once the active timestamp has been loaded, this validates the inserted manifest timestamp. 00491 * 00492 * DOT States: 00493 * DOT: VerifyTimestamp 00494 * DOT: VerifyTimestamp -> VerifyApplication 00495 * DOT: VerifyTimestamp -> VerifyFail [label="[Timestamp too old]"] 00496 */ 00497 static arm_uc_error_t state_verifyTimestamp(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00498 { 00499 arm_uc_error_t err = getLatestManifestTimestampFSM(*event); 00500 if (err.error == ERR_NONE) 00501 { 00502 err = ARM_UC_mmGetTimestamp(&ctx->manifest, &ctx->current_ts); 00503 } 00504 if (err.error == ERR_NONE) 00505 { 00506 #if MANIFEST_ROLLBACK_PROTECTION 00507 // Validate the timestamp for rollback protection. 00508 if (arm_uc_mmContext.max_ts >= arm_uc_mmContext.current_ts) 00509 { 00510 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_ROLLBACK); 00511 } 00512 else 00513 #endif 00514 { 00515 ARM_UC_MFST_SET_ERROR(err, MFST_ERR_NONE); 00516 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_APP; 00517 } 00518 } 00519 return err; 00520 } 00521 00522 /** @brief Calls out to a handler provided by the application. 00523 * @details Currently unimplemented. 00524 * 00525 * DOT States: 00526 * DOT: VerifyApplication 00527 * DOT: VerifyApplication -> VerifyDone 00528 * DOT: VerifyApplication -> VerifyFail [label="[App denied]"] 00529 */ 00530 static arm_uc_error_t state_verifyApplication(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00531 { 00532 arm_uc_error_t err = {MFST_ERR_NONE}; 00533 if (err.error == ERR_NONE) 00534 { 00535 ctx->state = ARM_UC_MM_INS_STATE_VERIFY_DONE; 00536 } 00537 return err; 00538 } 00539 /** @brief Verification has failed. 00540 * @details This state will never be entered. This is for documentation purposes only. The state machine exits when an 00541 * error is detected, so this state cannot be entered. The hub will be notified via the state machine's error 00542 * handler. 00543 * 00544 * DOT States: 00545 * DOT: VerifyFail 00546 * DOT: VerifyFail -> Idle 00547 */ 00548 00549 00550 /** @brief Verification has completed successfully. 00551 * @details This is a placeholder state that may be useful if more operations must be performed after verification, 00552 * for example, storage of the manifest. 00553 * 00554 * DOT States: 00555 * DOT: VerifyDone 00556 * DOT: VerifyDone -> AlertHub 00557 */ 00558 static arm_uc_error_t state_verifyDone(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00559 { 00560 arm_uc_error_t err = {MFST_ERR_NONE}; 00561 if (err.error == ERR_NONE) 00562 { 00563 ctx->state = ARM_UC_MM_INS_STATE_ALERT; 00564 } 00565 return err; 00566 } 00567 /** @brief Alert the hub that insert has finished processing the manifest. 00568 * @details Queues a callback to the hub, that reports completion. 00569 * 00570 * DOT States: 00571 * DOT: AlertHub 00572 * DOT: AlertHub -> Idle 00573 */ 00574 static arm_uc_error_t state_alertHub(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event) 00575 { 00576 arm_uc_error_t err = {MFST_ERR_NONE}; 00577 return err; 00578 } 00579 /** 00580 * DOT Teardown 00581 * DOT: } 00582 */ 00583 00584 arm_uc_error_t ARM_UC_mmInsertFSM(uint32_t event) 00585 { 00586 arm_uc_error_t err = {MFST_ERR_NONE}; 00587 struct arm_uc_mmInsertContext_t* ctx; 00588 if (arm_uc_mmPersistentContext.ctx == NULL || *arm_uc_mmPersistentContext.ctx == NULL) 00589 { 00590 return (arm_uc_error_t){MFST_ERR_NULL_PTR}; 00591 } 00592 ctx = &(*arm_uc_mmPersistentContext.ctx)->insert; 00593 00594 uint32_t oldState; 00595 #if ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS 00596 uint32_t oldEvent; 00597 #endif 00598 ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "> %s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event); 00599 do { 00600 // Preserve the old state to check for state transitions 00601 oldState = ctx->state; 00602 00603 #if ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS 00604 // Preserve the old event for testing 00605 oldEvent = event; 00606 #endif 00607 // Reset error logging 00608 arm_uc_mmPersistentContext.errorFile = NULL; 00609 arm_uc_mmPersistentContext.errorLine = 0; 00610 00611 ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "+ %s state: %s(%u)\n", __PRETTY_FUNCTION__, 00612 ARM_UC_mmInsertState2Str(ctx->state), (unsigned)ctx->state);\ 00613 switch (ctx->state) 00614 { 00615 case ARM_UC_MM_INS_STATE_IDLE: 00616 err = state_idle(ctx, &event); 00617 break; 00618 case ARM_UC_MM_INS_STATE_BEGIN: 00619 err = state_begin(ctx, &event); 00620 break; 00621 case ARM_UC_MM_INS_STATE_VERIFY_BASIC_PARAMS: 00622 err = state_verifyBasicParameters(ctx, &event); 00623 break; 00624 case ARM_UC_MM_INS_STATE_HASH_VERIFY: 00625 err = state_verifyHash(ctx, &event); 00626 break; 00627 case ARM_UC_MM_INS_STATE_VERIFY_SIG_LOOP: 00628 err = state_verifySignatureLoopStart(ctx, &event); 00629 break; 00630 case ARM_UC_MM_INS_STATE_VERIFY_SIG_START: 00631 err = state_verifySignatureStart(ctx, &event); 00632 break; 00633 case ARM_UC_MM_INS_STATE_VERIFY_SIG_WAIT: 00634 err = state_verifySignature(ctx, &event); 00635 break; 00636 case ARM_UC_MM_INS_STATE_VERIFY_PARAMS: 00637 err = state_verifyParameters(ctx, &event); 00638 break; 00639 case ARM_UC_MM_INS_STATE_VERIFY_TS_START: 00640 err = state_verifyTimestampStart(ctx, &event); 00641 break; 00642 case ARM_UC_MM_INS_STATE_VERIFY_TS: 00643 err = state_verifyTimestamp(ctx, &event); 00644 break; 00645 case ARM_UC_MM_INS_STATE_VERIFY_APP: 00646 err = state_verifyApplication(ctx, &event); 00647 break; 00648 case ARM_UC_MM_INS_STATE_VERIFY_DONE: 00649 err = state_verifyDone(ctx, &event); 00650 break; 00651 case ARM_UC_MM_INS_STATE_ALERT: 00652 err = state_alertHub(ctx, &event); 00653 break; 00654 case ARM_UC_MM_INS_STATE_INVALID: 00655 default: 00656 err = (arm_uc_error_t){MFST_ERR_INVALID_STATE}; 00657 break; 00658 } 00659 #if ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS 00660 if (arm_uc_mmPersistentContext.testHook) 00661 { 00662 arm_uc_mmPersistentContext.testHook("insert", *arm_uc_mmPersistentContext.ctx, oldState, oldEvent, err); 00663 } 00664 #endif 00665 } while (err.code == MFST_ERR_NONE && oldState != ctx->state); 00666 ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "< %s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err)); 00667 return err; 00668 }
Generated on Tue Jul 12 2022 19:12:11 by
1.7.2
