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