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_mmInit.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_mmInit.h" 00020 #include "arm_uc_mmCommon.h" 00021 #if !MANIFEST_MANAGER_NO_STORAGE 00022 #include "update-client-manifest-manager/update-client-manifest-manager-context.h" 00023 #include "arm_uc_mmGetLatestTimestamp.h" 00024 #include "arm_uc_mm_derparse.h" 00025 #include "cfstore-fsm.h" 00026 #include "crypto-fsm.h" 00027 #include "accessors.h" 00028 #include "update-client-common/arm_uc_types.h" 00029 #include "update-client-common/arm_uc_common.h" 00030 #include "update-client-common/arm_uc_error.h" 00031 #include "mbedtls/sha256.h" 00032 00033 #include "arm_uc_mmFSMHelper.h" 00034 00035 #ifndef min 00036 #define min(X,Y) ((X) < (Y) ? (X) : (Y)) 00037 #endif 00038 00039 const char* ARM_UC_mmInitState2Str(uint32_t state) 00040 { 00041 switch (state) { 00042 #define ENUM_AUTO(name) case name: return #name; 00043 #define ENUM_FIXED(name, val) ENUM_AUTO(name) 00044 ARM_UC_MM_INIT_STATE_LIST 00045 #undef ENUM_FIXED 00046 #undef ENUM_AUTO 00047 default: 00048 return "Unknown State"; 00049 } 00050 } 00051 00052 00053 00054 arm_uc_error_t arm_uc_mmInitFSM(uint32_t event) 00055 { 00056 if (arm_uc_mmPersistentContext.ctx == NULL || *arm_uc_mmPersistentContext.ctx == NULL) 00057 { 00058 return (arm_uc_error_t){MFST_ERR_NULL_PTR}; 00059 } 00060 struct arm_uc_mmInitContext_t* ctx = &(*arm_uc_mmPersistentContext.ctx)->init; 00061 arm_uc_error_t err = {MFST_ERR_PENDING}; 00062 00063 ARM_UC_MM_FSM_HELPER_START(*ctx, ARM_UC_mmInitState2Str){ 00064 case ARM_UC_MM_INIT_BEGIN: 00065 // Find the latest manifest. 00066 ARM_UC_MM_SET_BUFFER(ctx->keyPath, ctx->pathBuffer); 00067 err = getLatestManifestTimestamp(&ctx->timestamp, &ctx->keyPath); 00068 ctx->state = ARM_UC_MM_INIT_LATEST_MFST; 00069 // clear the missing dep flag 00070 ctx->missingDep = 0; 00071 // Set the root manifest flag 00072 ctx->root = 1; 00073 00074 event = ARM_UC_MM_EVENT_BEGIN; 00075 break; 00076 case ARM_UC_MM_INIT_LATEST_MFST: 00077 { 00078 err = getLatestManifestTimestampFSM(event); 00079 if (err.code != MFST_ERR_NONE) 00080 { 00081 break; 00082 } 00083 if (ctx->timestamp == 0) 00084 { 00085 err.code = MFST_ERR_NO_MANIFEST; 00086 break; 00087 } 00088 // Copy out the root manifest's base path 00089 strncpy((char*)ctx->rootManifestBasePath, (char*)ctx->keyPath.ptr, sizeof(ctx->rootManifestBasePath)-1); 00090 ctx->rootManifestBasePath[sizeof(ctx->rootManifestBasePath)-1] = 0; 00091 // Modify the key path. 00092 char* pos = (char*)ctx->keyPath.ptr + strlen((char*)ctx->keyPath.ptr) - strlen("ts"); 00093 *pos = 'm'; 00094 *(pos + 1) = 0; 00095 // Setup the manifest buffer 00096 ARM_UC_MM_SET_BUFFER(ctx->manifest, ctx->manifestBuffer); 00097 // Find the manifest 00098 err = ARM_UC_mmCfStoreFindKey(&ctx->keyPath); 00099 if (err.code != MFST_ERR_NONE) 00100 { 00101 break; 00102 } 00103 event = ARM_UC_MM_EVENT_CF_BEGIN; 00104 ctx->state = ARM_UC_MM_INIT_FINDING; 00105 // no break; 00106 } 00107 case ARM_UC_MM_INIT_FINDING: 00108 if (event == UCMM_EVENT_CF_FIND_FAILED) 00109 { 00110 if (ctx->root) 00111 { 00112 //TODO: assert! This should not be possible! 00113 err.code = MFST_ERR_INVALID_STATE; 00114 } else { 00115 // No more deps to find. 00116 err.code = MFST_ERR_NONE; 00117 } 00118 break; 00119 } 00120 err = ARM_UC_mmCfStoreFindKeyFSM(event); 00121 if (err.code != MFST_ERR_NONE) 00122 { 00123 break; 00124 } 00125 // Read the manifest 00126 err = ARM_UC_mmCfStoreReadLastKey(&ctx->manifest); 00127 if (err.code != MFST_ERR_NONE) { 00128 break; 00129 } 00130 event = ARM_UC_MM_EVENT_CF_BEGIN; 00131 ctx->state = ARM_UC_MM_INIT_READING; 00132 // no break; 00133 case ARM_UC_MM_INIT_READING: 00134 // Read the manifest into a buffer 00135 err = ARM_UC_mmCfStoreReadLastKeyFSM(event); 00136 if (err.code != MFST_ERR_NONE) 00137 { 00138 break; 00139 } 00140 ctx->state = ARM_UC_MM_INIT_STATE_HASH_VERIFY; 00141 // Preserve the manifest key 00142 ARM_UC_mmCfStorePreserveLastKey(); 00143 00144 // no break; 00145 case ARM_UC_MM_INIT_STATE_HASH_VERIFY: 00146 // Verify the manifest hash 00147 err = ucmmValidateManifestHash(&ctx->manifest); 00148 if (err.code == MFST_ERR_NONE) { 00149 uint32_t val; 00150 err = ARM_UC_mmGetCryptoMode(&ctx->manifest, &val); 00151 if (err.code != MFST_ERR_NONE) 00152 { 00153 break; 00154 } 00155 ucmm_crypto_flags_t cryptoMode = ARM_UC_mmGetCryptoFlags(val); 00156 if(cryptoMode.ecc || cryptoMode.rsa) { 00157 ctx->state = ARM_UC_MM_INIT_STATE_PK_VERIFY; 00158 } else { 00159 ctx->state = ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN; 00160 } 00161 } 00162 break; 00163 case ARM_UC_MM_INIT_STATE_PK_VERIFY: 00164 // Verify the manifest signature 00165 err = ucmmValidateSignature(&ctx->manifest); 00166 if (err.code == MFST_ERR_NONE) 00167 { 00168 ctx->state = ARM_UC_MM_INIT_STATE_PK_VERIFYING; 00169 } 00170 break; 00171 case ARM_UC_MM_INIT_STATE_PK_VERIFYING: 00172 err = ucmmValidateSignatureFSM(event); 00173 if (err.code == MFST_ERR_NONE) 00174 { 00175 ctx->state = ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN; 00176 } 00177 break; 00178 case ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN: 00179 // ATTACKVECTOR: If an attacker can add a manifest to the dependency prefix in the config store, the manifest 00180 // manager has no way to know that it is not valid, due to the flat file heirarchy. 00181 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_MANIFEST_BEGIN; 00182 // NO BREAK; 00183 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_MANIFEST_BEGIN: 00184 // Loop: manifest 00185 // Set the depidx to 0 00186 ctx->depidx = 0; 00187 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH; 00188 // NO BREAK; 00189 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH: 00190 { 00191 arm_uc_buffer_t dependency; 00192 arm_uc_buffer_t hash; 00193 // Read the dependency at depidx 00194 err = ARM_UC_mmGetManifestLinksElement(&ctx->manifest, ctx->depidx, &dependency); 00195 // If there isn't one 00196 if (err.code != MFST_ERR_NONE) 00197 { 00198 break; 00199 } 00200 if (dependency.ptr == NULL) 00201 { 00202 // Exit Loop: dependency 00203 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_END; 00204 err.code = MFST_ERR_NONE; 00205 break; 00206 } 00207 // Get the dependency hash 00208 err = ARM_UC_mmGetManifestLinksHash(&dependency, &hash); 00209 if (err.code != MFST_ERR_NONE) 00210 { 00211 break; 00212 } 00213 // Store the dependency hash 00214 memcpy(ctx->currentHash, hash.ptr, min(hash.size, sizeof(ctx->currentHash))); 00215 // Format the dependency search key 00216 // The result of this operation is: 00217 // com.arm.mbed.update.mm.m.<root manifest hash>.deps.<dependency hash>.m 00218 // ASSUMES sizeof keypath > sizeof rootManifestBasePath 00219 strncpy((char*)ctx->keyPath.ptr, (char*)ctx->rootManifestBasePath, sizeof(ctx->keyPath.ptr)); 00220 ctx->keyPath.size = strlen(ctx->keyPath.ptr); 00221 // Back up one space to remove the 'm' 00222 strncpy((char*)ctx->keyPath.ptr + ctx->keyPath.size-1, "deps.", ctx->keyPath.size_max - ctx->keyPath.size); 00223 ctx->keyPath.size = strlen(ctx->keyPath.ptr); 00224 ARM_UC_Base64Enc(ctx->keyPath.ptr + ctx->keyPath.size, ctx->keyPath.size_max - ctx->keyPath.size, &hash); 00225 ctx->keyPath.size = strlen(ctx->keyPath.ptr); 00226 strncpy((char*)ctx->keyPath.ptr + ctx->keyPath.size, ".m", ctx->keyPath.size_max - ctx->keyPath.size); 00227 ctx->keyPath.size += 3; // add one for null terminator 00228 00229 // Find the dependency in the config store 00230 err = ucmmCfstoreFindAndRead((char*)ctx->keyPath.ptr, &ctx->manifest); 00231 if (err.code == MFST_ERR_NONE) 00232 { 00233 event = ARM_UC_MM_EVENT_BEGIN; 00234 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_READING_DEPENDENCY; 00235 } 00236 break; 00237 } 00238 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_READING_DEPENDENCY: 00239 // If there is no matching dependency 00240 if (event == UCMM_EVENT_CF_FIND_FAILED) 00241 { 00242 // Set the missing dep flag 00243 ctx->missingDep = 1; 00244 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK; 00245 // Continue... 00246 err.code = MFST_ERR_NONE; 00247 break; 00248 } 00249 // Find/Read the dependency manifest 00250 err = ucmmCfstoreFindAndReadFSM(event); 00251 if (err.code != MFST_ERR_NONE) 00252 { 00253 break; 00254 } 00255 // There is a matching dependency 00256 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_CHECK_HASH; 00257 // No break; 00258 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_CHECK_HASH: 00259 { 00260 #if MAX_HASH_BYTES != 256/8 00261 #error Hash size mismatch 00262 #endif 00263 uint8_t localhash[MAX_HASH_BYTES]; 00264 arm_uc_buffer_t local = { 00265 .size_max = MAX_HASH_BYTES, 00266 .size = 256/8, 00267 .ptr = localhash 00268 }; 00269 arm_uc_buffer_t resource; 00270 const int32_t valueID = ARM_UC_MM_DER_RESOURCE; 00271 int rc = ARM_UC_mmDERGetSignedResourceValues(&resource, 1, &valueID, &resource); 00272 if (rc) 00273 { 00274 err.code = MFST_ERR_DER_FORMAT; 00275 break; 00276 } 00277 { 00278 // Calculate the dependency hash 00279 mbedtls_sha256_context ctx; 00280 mbedtls_sha256_init(&ctx); 00281 mbedtls_sha256_starts(&ctx, 0); 00282 mbedtls_sha256_update(&ctx, resource.ptr, resource.size); 00283 mbedtls_sha256_finish(&ctx, local.ptr); 00284 } 00285 { 00286 arm_uc_buffer_t remote = { 00287 .size_max = MAX_HASH_BYTES, 00288 .size = 256/8, 00289 .ptr = ctx->currentHash 00290 }; 00291 // Validate the dependency hash 00292 if(ARM_UC_BinCompareCT(&local, &remote)) 00293 { 00294 // If invalid, Set the missing dep flag 00295 ctx->missingDep = 1; 00296 // Delete the manifest 00297 ARM_UC_mmCfStoreDeleteLastKey(); 00298 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_DELETE; 00299 event = ARM_UC_MM_EVENT_CF_BEGIN; 00300 } 00301 else 00302 { 00303 // End Loop: dependency 00304 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ; 00305 // Increment the depidx 00306 ctx->depidx++; 00307 } 00308 } 00309 break; 00310 } 00311 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_DELETE: 00312 err = ARM_UC_mmCfStoreDeleteLastKeyFSM(event); 00313 if (err.code == MFST_ERR_NONE) 00314 { 00315 // Make sure a URI exists. 00316 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK; 00317 } 00318 break; 00319 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK: 00320 { 00321 // modify the search path 00322 char* pos = (char*)ctx->keyPath.ptr + ctx->keyPath.size - 2; // null terminator 00323 strncpy(pos, "uri", ctx->keyPath.size_max - (ctx->keyPath.size - 2)); // null terminator 00324 // Check if there is a URI entry 00325 // HACK: No API for find without ovewriting the existing stored key. Use find/read even though we don't need the 00326 // data. 00327 err = ucmmCfstoreFindAndRead((char*)ctx->keyPath.ptr, &ctx->manifest); 00328 if (err.code != MFST_ERR_NONE) 00329 { 00330 break; 00331 } 00332 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECKING; 00333 event = ARM_UC_MM_EVENT_CF_BEGIN; 00334 // no break 00335 } 00336 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECKING: 00337 if (event == UCMM_EVENT_CF_FIND_FAILED) 00338 { 00339 // TODO: Erase all deps and start over. 00340 err.code = MFST_ERR_INVALID_STATE; 00341 break; 00342 } 00343 err = ucmmCfstoreFindAndReadFSM(event); 00344 if (err.code == MFST_ERR_NONE) 00345 { 00346 // Increment the depidx 00347 ctx->depidx++; 00348 // End Loop: dependency 00349 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ; 00350 } 00351 break; 00352 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ: 00353 // Loop: dependency 00354 // Restore the manifest key 00355 ARM_UC_mmCfStoreRestoreLastKey(); 00356 // Seek the current key 00357 err = ARM_UC_mmCfStoreSeekLastKey(0); 00358 if (err.code == MFST_ERR_NONE) 00359 { 00360 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_SEEKING; 00361 } 00362 break; 00363 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_SEEKING: 00364 err = ARM_UC_mmCfStoreSeekLastKeyFSM(event); 00365 if (err.code != MFST_ERR_NONE) 00366 { 00367 break; 00368 } 00369 // Read the current key 00370 err = ARM_UC_mmCfStoreReadLastKey(&ctx->manifest); 00371 if (err.code != MFST_ERR_NONE) 00372 { 00373 break; 00374 } 00375 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READING; 00376 event = ARM_UC_MM_EVENT_CF_BEGIN; 00377 // no break 00378 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READING: 00379 err = ARM_UC_mmCfStoreReadLastKeyFSM(event); 00380 if (err.code == MFST_ERR_NONE) 00381 { 00382 ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH; 00383 // Preserve the manifest key 00384 ARM_UC_mmCfStorePreserveLastKey(); 00385 } 00386 break; 00387 case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_END: 00388 // Format the dependency search key 00389 strncpy((char*)ctx->keyPath.ptr, (char*)ctx->rootManifestBasePath, sizeof(ctx->rootManifestBasePath)); 00390 ctx->keyPath.size = sizeof(ctx->rootManifestBasePath)-1; 00391 strncpy((char*)ctx->keyPath.ptr + ctx->keyPath.size, ".deps.*", ctx->keyPath.size_max - ctx->keyPath.size); 00392 ctx->keyPath.size += sizeof(".deps.*") - 1; 00393 // If the root flag is set 00394 if (ctx->root) 00395 { 00396 // Clear the root flag 00397 ctx->root = 0; 00398 // Start the dependency search 00399 err = ARM_UC_mmCfStoreFindKey(&ctx->keyPath); 00400 } 00401 else 00402 { 00403 // Continue the dependency search 00404 err = ARM_UC_mmCfStoreFindNextKey(); 00405 } 00406 if (err.code == MFST_ERR_NONE) 00407 { 00408 event = ARM_UC_MM_EVENT_CF_BEGIN; 00409 // End Loop: manifest 00410 ctx->state = ARM_UC_MM_INIT_FINDING; 00411 } 00412 break; 00413 default: 00414 err.code = MFST_ERR_INVALID_STATE; 00415 break; 00416 } ARM_UC_MM_FSM_HELPER_FINISH(*ctx); 00417 if (err.code == MFST_ERR_NONE && ctx->missingDep == 1) 00418 { 00419 // TODO: Configure & trigger insert FSM 00420 } 00421 return err; 00422 } 00423 00424 #endif // !MANIFEST_MANAGER_NO_STORAGE
Generated on Tue Jul 12 2022 19:12:11 by
1.7.2
