Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_mmFetchFirmwareInfo.c Source File

arm_uc_mmFetchFirmwareInfo.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_mmDerManifestAccessors.h"
00023 #include "arm_uc_mmDerManifestParser.h"
00024 #include "arm_uc_mmFSMHelper.h"
00025 #include "update-client-common/arm_uc_scheduler.h"
00026 
00027 #include "update-client-manifest-manager/update-client-manifest-manager.h"
00028 #include "update-client-manifest-manager/update-client-manifest-types.h"
00029 
00030 
00031 #include <stdint.h>
00032 #include <stdio.h>
00033 #include <stddef.h>
00034 #include <string.h>
00035 
00036 
00037 #undef ARRAY_SIZE
00038 #define ARRAY_SIZE(ENUM_AUTO)\
00039     (sizeof(ENUM_AUTO)/sizeof((ENUM_AUTO)[0]))
00040 
00041 
00042 #define ARM_UC_MM_MFST_IMAGE_REF_FIELDS \
00043     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
00044     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
00045     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
00046     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
00047     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
00048 
00049 static const int32_t imageRefFields [] = {
00050 #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
00051     ARM_UC_MM_MFST_IMAGE_REF_FIELDS
00052 #undef ENUM_AUTO
00053 };
00054 enum imageRefFieldIdxs {
00055 #define ENUM_AUTO(ENUM_AUTO) IRF_ ## ENUM_AUTO ## _IDX,
00056     ARM_UC_MM_MFST_IMAGE_REF_FIELDS
00057 #undef ENUM_AUTO
00058 };
00059 
00060 #if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
00061 static const char *ARM_UC_mmFwState2Str(uint32_t state)
00062 {
00063     switch (state) {
00064 #define ENUM_AUTO(name) case name: return #name;
00065 #define ENUM_FIXED(name, val) ENUM_AUTO(name)
00066             ARM_UC_MM_FW_STATE_LIST
00067 #undef ENUM_AUTO
00068 #undef ENUM_FIXED
00069         default:
00070             return "Unknown State";
00071     }
00072 }
00073 #endif
00074 
00075 int ARM_UC_mmGetImageRef(manifest_firmware_info_t *info, arm_uc_buffer_t *mfst_fwref)
00076 {
00077     arm_uc_buffer_t buffers[ARRAY_SIZE(imageRefFields)];
00078     int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
00079                                    mfst_fwref,
00080                                    ARRAY_SIZE(imageRefFields),
00081                                    imageRefFields,
00082                                    buffers);
00083     if (rc == 0) {
00084         // Found local key ID and encrypted key
00085         info->cipherMode = ARM_UC_MM_CIPHERMODE_NONE;
00086         // TODO: Handle non-enum format
00087         uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[IRF_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
00088         memset(&info->format, 0, sizeof(info->format));
00089         info->format.words[RFC_4122_WORDS - 1] = htobe(format);
00090 
00091         ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[IRF_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
00092         ARM_UC_buffer_shallow_copy(&info->hash, &buffers[IRF_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
00093         ARM_UC_buffer_shallow_copy(&info->uri, &buffers[IRF_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
00094         info->size = ARM_UC_mmDerBuf2Uint(&buffers[IRF_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
00095     }
00096     return rc;
00097 }
00098 
00099 #define ARM_UC_MM_MFST_CRYPT_LOCAL_ID_FIELDS \
00100     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
00101     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
00102     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_LOCAL)\
00103     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY)\
00104     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
00105     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
00106     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
00107     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
00108 
00109 static const int32_t localEncKeyFields [] = {
00110 #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
00111     ARM_UC_MM_MFST_CRYPT_LOCAL_ID_FIELDS
00112 #undef ENUM_AUTO
00113 };
00114 enum localEncKeyFieldIdxs {
00115 #define ENUM_AUTO(ENUM_AUTO) LEK_ ## ENUM_AUTO ## _IDX,
00116     ARM_UC_MM_MFST_CRYPT_LOCAL_ID_FIELDS
00117 #undef ENUM_AUTO
00118 };
00119 
00120 int ARM_UC_mmGetLocalIDAndKey(manifest_firmware_info_t *info, arm_uc_buffer_t *mfst_fwref)
00121 {
00122     arm_uc_buffer_t buffers[ARRAY_SIZE(localEncKeyFields)];
00123     int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
00124                                    mfst_fwref,
00125                                    ARRAY_SIZE(localEncKeyFields),
00126                                    localEncKeyFields,
00127                                    buffers);
00128     if (rc == 0) {
00129         // Found local key ID and encrypted key
00130         info->cipherMode = ARM_UC_MM_CIPHERMODE_PSK;
00131         // TODO: Handle non-enum format
00132         uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[LEK_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
00133         memset(&info->format, 0, sizeof(info->format));
00134         info->format.words[RFC_4122_WORDS - 1] = htobe(format);
00135         ARM_UC_buffer_shallow_copy(&info->initVector, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_CRYPT_IV_IDX]);
00136         ARM_UC_buffer_shallow_copy(&info->psk.keyID, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
00137         ARM_UC_buffer_shallow_copy(&info->psk.cipherKey, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY_IDX]);
00138 
00139         ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
00140         ARM_UC_buffer_shallow_copy(&info->hash, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
00141         ARM_UC_buffer_shallow_copy(&info->uri, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
00142         info->size = ARM_UC_mmDerBuf2Uint(&buffers[LEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
00143     }
00144     return rc;
00145 }
00146 
00147 
00148 #define ARM_UC_MM_MFST_CRYPT_CERT_KEY_FIELDS \
00149     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
00150     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
00151     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT)\
00152     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL)\
00153     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY)\
00154     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
00155     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
00156     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
00157     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
00158 
00159 static const int32_t certEncKeyFields [] = {
00160 #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
00161     ARM_UC_MM_MFST_CRYPT_CERT_KEY_FIELDS
00162 #undef ENUM_AUTO
00163 };
00164 
00165 enum certEncKeyFieldIdxs {
00166 #define ENUM_AUTO(ENUM_AUTO) CEK_ ## ENUM_AUTO ## _IDX,
00167     ARM_UC_MM_MFST_CRYPT_CERT_KEY_FIELDS
00168 #undef ENUM_AUTO
00169 };
00170 
00171 int ARM_UC_mmGetCertAndKey(manifest_firmware_info_t *info, arm_uc_buffer_t *mfst_fwref)
00172 {
00173     arm_uc_buffer_t buffers[ARRAY_SIZE(certEncKeyFields)];
00174     int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
00175                                    mfst_fwref,
00176                                    ARRAY_SIZE(certEncKeyFields),
00177                                    certEncKeyFields,
00178                                    buffers);
00179     if (rc == 0) {
00180         info->cipherMode = ARM_UC_MM_CIPHERMODE_CERT_CIPHERKEY;
00181         // TODO: Handle non-enum format
00182         uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[CEK_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
00183         memset(&info->format, 0, sizeof(info->format));
00184         info->format.words[RFC_4122_WORDS - 1] = htobe(format);
00185         ARM_UC_buffer_shallow_copy(&info->initVector, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_IV_IDX]);
00186 
00187         ARM_UC_buffer_shallow_copy(&info->certCK.certFingerPrint,
00188                                    &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT_IDX]);
00189         ARM_UC_buffer_shallow_copy(&info->certCK.certURL, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL_IDX]);
00190         ARM_UC_buffer_shallow_copy(&info->certCK.cipherKey, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY_IDX]);
00191 
00192         ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
00193         ARM_UC_buffer_shallow_copy(&info->hash, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
00194         ARM_UC_buffer_shallow_copy(&info->uri, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
00195         info->size = ARM_UC_mmDerBuf2Uint(&buffers[CEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
00196     }
00197     return rc;
00198 }
00199 
00200 
00201 #define ARM_UC_MM_MFST_CRYPT_CERT_KEYTABLE_FIELDS \
00202     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
00203     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
00204     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT)\
00205     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL)\
00206     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF)\
00207     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
00208     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
00209     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
00210     ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
00211 
00212 static const int32_t certKeyTableFields [] = {
00213 #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
00214     ARM_UC_MM_MFST_CRYPT_CERT_KEYTABLE_FIELDS
00215 #undef ENUM_AUTO
00216 };
00217 
00218 enum certKeyTableFieldIdxs {
00219 #define ENUM_AUTO(ENUM_AUTO) CKT_ ## ENUM_AUTO ## _IDX,
00220     ARM_UC_MM_MFST_CRYPT_CERT_KEYTABLE_FIELDS
00221 #undef ENUM_AUTO
00222 };
00223 
00224 int ARM_UC_mmGetCertAndKeyTable(manifest_firmware_info_t *info, arm_uc_buffer_t *mfst_fwref)
00225 {
00226     arm_uc_buffer_t buffers[ARRAY_SIZE(certKeyTableFields)];
00227     int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
00228                                    mfst_fwref,
00229                                    ARRAY_SIZE(certKeyTableFields),
00230                                    certKeyTableFields,
00231                                    buffers);
00232     if (rc == 0) {
00233         info->cipherMode = ARM_UC_MM_CIPHERMODE_CERT_KEYTABLE;
00234         // TODO: Handle non-enum format
00235         uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[CKT_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
00236         memset(&info->format, 0, sizeof(info->format));
00237         info->format.words[RFC_4122_WORDS - 1] = htobe(format);
00238         ARM_UC_buffer_shallow_copy(&info->initVector, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_IV_IDX]);
00239 
00240         ARM_UC_buffer_shallow_copy(&info->certKT.certFingerPrint,
00241                                    &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT_IDX]);
00242         ARM_UC_buffer_shallow_copy(&info->certKT.certURL, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL_IDX]);
00243         ARM_UC_buffer_shallow_copy(&info->certKT.keyTableURL, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF_IDX]);
00244 
00245         ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
00246         ARM_UC_buffer_shallow_copy(&info->hash, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
00247         ARM_UC_buffer_shallow_copy(&info->uri, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
00248         info->size = ARM_UC_mmDerBuf2Uint(&buffers[CKT_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
00249     }
00250     return rc;
00251 }
00252 
00253 arm_uc_error_t ARM_UC_mmFetchFirmwareInfoFSM(uint32_t event)
00254 {
00255     arm_uc_error_t err = {ERR_NONE};
00256     if (arm_uc_mmPersistentContext.ctx == NULL || *arm_uc_mmPersistentContext.ctx == NULL) {
00257         return (arm_uc_error_t) {MFST_ERR_NULL_PTR};
00258     }
00259     struct arm_uc_mm_fw_context_t *ctx = &(*arm_uc_mmPersistentContext.ctx)->getFw;
00260     if (ctx->info == NULL) {
00261         return (arm_uc_error_t) {MFST_ERR_NULL_PTR};
00262     }
00263     ARM_UC_MM_FSM_HELPER_START(*ctx, ARM_UC_mmFwState2Str) {
00264     case ARM_UC_MM_FW_STATE_IDLE:
00265         err = (arm_uc_error_t) {ERR_NONE};
00266         break;
00267     case ARM_UC_MM_FW_STATE_BEGIN: {
00268             // If there is no manifest storage, assume it is still present in the input buffer
00269             ctx->state = ARM_UC_MM_FW_STATE_READ_URI;
00270             ARM_UC_MM_SET_BUFFER(ctx->current_data, ctx->info->manifestBuffer);
00271             ctx->current_data.size = ctx->info->manifestSize;
00272             break;
00273         }
00274     case ARM_UC_MM_FW_STATE_READ_URI: {
00275             // Get the encryption mode and the firmware info block.
00276             const int32_t fieldIDs [] = {ARM_UC_MM_DER_MFST_ENC_ENUM, ARM_UC_MM_DER_MFST_FIRMWARE};
00277             arm_uc_buffer_t buffers [sizeof(fieldIDs) / sizeof(fieldIDs[0])];
00278             int rc = ARM_UC_mmDERGetSignedResourceValues(
00279                          &ctx->current_data,
00280                          sizeof(fieldIDs) / sizeof(fieldIDs[0]),
00281                          fieldIDs,
00282                          buffers);
00283             if (rc < 0) {
00284                 err.code = MFST_ERR_DER_FORMAT;
00285                 break;
00286             } else if (rc > 0) {
00287                 // in storage mode, firmware must be supplied.
00288                 err.code = MFST_ERR_EMPTY_FIELD;
00289                 break;
00290             }
00291             arm_uc_buffer_t fwBuf;
00292             ARM_UC_buffer_shallow_copy(&fwBuf, &buffers[1]);
00293 
00294             // Store timestamp
00295             ARM_UC_MM_SET_BUFFER(ctx->current_data, ctx->info->manifestBuffer);
00296             ctx->current_data.size = ctx->info->manifestSize;
00297             err = ARM_UC_mmGetTimestamp(&ctx->current_data, &ctx->info->timestamp);
00298             if (err.error != 0) {
00299                 break;
00300             }
00301 
00302             ctx->info->cipherMode = ARM_UC_MM_CIPHERMODE_NONE;
00303             // Found an encryption mode and firmware!
00304             uint32_t cryptoMode = ARM_UC_mmDerBuf2Uint(&buffers[0]);
00305             if (!ARM_UC_mmGetCryptoFlags(cryptoMode).aes) {
00306                 // Encryption not in use. Skip key, ID, and IV extraction.
00307                 rc = ARM_UC_mmGetImageRef(ctx->info, &fwBuf);
00308                 if (rc == 0) {
00309                     ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
00310                     err.code = ERR_NONE;
00311                 } else {
00312                     err.code = MFST_ERR_DER_FORMAT;
00313                 }
00314                 break;
00315             }
00316             // There are three possible combinations of encryption info:
00317             // local key ID & encrypted key
00318             rc = ARM_UC_mmGetLocalIDAndKey(ctx->info, &fwBuf);
00319             if (!rc) {
00320                 ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
00321                 err.code = ERR_NONE;
00322                 break;
00323             }
00324             // Certificate and encrypted key
00325             rc = ARM_UC_mmGetCertAndKey(ctx->info, &fwBuf);
00326             if (!rc) {
00327                 ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
00328                 err.code = ERR_NONE;
00329                 break;
00330             }
00331             // Certificate and key table reference
00332             rc = ARM_UC_mmGetCertAndKeyTable(ctx->info, &fwBuf);
00333             if (!rc) {
00334                 ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
00335                 err.code = ERR_NONE;
00336                 break;
00337             }
00338 
00339             break;
00340         }
00341     case ARM_UC_MM_FW_STATE_GET_FW_REF:
00342 
00343         // TODO: Ref only
00344     case ARM_UC_MM_FW_STATE_NOTIFY:
00345         ctx->state = ARM_UC_MM_FW_STATE_ROOT_NOTIFY_WAIT;
00346         err.code = MFST_ERR_PENDING;
00347         ARM_UC_PostCallback(&ctx->callbackStorage, arm_uc_mmPersistentContext.applicationEventHandler, ARM_UC_MM_RC_NEED_FW);
00348         break;
00349 
00350     case ARM_UC_MM_FW_STATE_ROOT_NOTIFY_WAIT:
00351         if (event == ARM_UC_MM_EVENT_BEGIN) {
00352             err.code = ERR_NONE;
00353             ctx->state = ARM_UC_MM_FW_STATE_DONE;
00354         }
00355         break;
00356     case ARM_UC_MM_FW_STATE_DONE:
00357         // NOTE: The outer FSM will send the "done" message.
00358         ctx->state = ARM_UC_MM_FW_STATE_IDLE;
00359         break;
00360     case ARM_UC_MM_FW_STATE_INVALID:
00361     default:
00362         err = (arm_uc_error_t) {MFST_ERR_INVALID_STATE};
00363         break;
00364     }
00365     ARM_UC_MM_FSM_HELPER_FINISH(*ctx);
00366     return err;
00367 }