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