Jim Carver
/
mbed-cloud-workshop-connect-HTS221
bug fix
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 #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 21:04:54 by 1.7.2