Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_mmCryptoUtils.c Source File

arm_uc_mmCryptoUtils.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_mmDerManifestParser.h"
00023 #include "update-client-common/arm_uc_crypto.h"
00024 
00025 #include "update-client-control-center/arm_uc_certificate.h"
00026 
00027 #include "arm_uc_mmDerManifestAccessors.h"
00028 #include "update-client-manifest-manager/update-client-manifest-manager.h"
00029 
00030 #include <string.h>
00031 
00032 void ARM_UC_mmVerifySignatureEntry(uint32_t event);
00033 /**
00034  * @file Cryptographic utilities
00035  * This file provides two primary APIs:
00036  * * Verifying manifest hashes
00037  * * Verifying manifest signatures
00038  *
00039  * Some utility functions used by other files in this module are also provided.
00040  *
00041  * Algorithm support:
00042  * ECC is currently supported, but RSA is not.
00043  * Currently, only ECC secp256r1 (prime256v1) is supported.
00044  * Currently, only SHA256 is supported.
00045  * HMAC is not yet supported.
00046  */
00047 
00048 /**
00049  * @brief Returns the sizes of the cryptographic primitives used by the supplied manifest.
00050  * @details Extracts the cryptomode field from a manifest and returns a struct that describes the size of cryptographic
00051  *          primitives used in the manifest. The supplied manifest must have been validated. No validation is performed
00052  *          by this function.
00053  *
00054  * @param[in]  buffer A buffer that contains a validated manifest.
00055  * @return            A struct cryptsize, which contains the AES primitive sizes and SHA primitive size, both in bytes.
00056  *                    An invalid cryptographic mode specifier will cause primitive sizes of `0` to be returned.
00057  */
00058 struct cryptsize getCryptInfo(arm_uc_buffer_t* buffer)
00059 {
00060     struct cryptsize cs = {0};
00061     uint32_t cryptoMode = 1U; // default SHA256 and ECC
00062     ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
00063 
00064     switch(cryptoMode)
00065     {
00066         case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00067         // case MFST_CRYPT_SHA256_HMAC_AES128_PSK:
00068             cs.aeslen = 128/CHAR_BIT;
00069             // fall through
00070         // case MFST_CRYPT_SHA256_HMAC:
00071         case MFST_CRYPT_SHA256:
00072             cs.hashlen = 256/CHAR_BIT;
00073             break;
00074         case MFST_CRYPT_SHA256_ECC:
00075             cs.hashlen = 256/CHAR_BIT;
00076         default:
00077             break;
00078     }
00079     return cs;
00080 }
00081 
00082 /**
00083  * @brief Converts a cryptographic mode enum to a structure with mode identifiers
00084  * @details In order to simplify many tests, the cryptographic mode identifier is converted into a structure of mode
00085  *          identifiers, one for each cryptographic primitive. This allows other parts of the code to examine the mode
00086  *          of one particular primitive without testing against many enums. This function performs no validation. The
00087  *          calling function should have performed validation in advance. If the cryptoMode is unrecognized, then a
00088  *          return will be populated with 0 for every flag.
00089  *
00090  *          HMAC modes are not currently supported.
00091  * TODO: Convert flags to enums
00092  * @param[in]  cryptoMode The cryptographic mode enum that specifies the settings for each primitive
00093  * @return                A structure of flags that indicate the mode of:
00094  *                        * Hash algorithm
00095  *                        * MAC
00096  *                        * Symmetric Encryption
00097  *                        * Pre-shared keys
00098  *                        * Public Key modes
00099  */
00100 arm_uc_mm_crypto_flags_t ARM_UC_mmGetCryptoFlags(uint32_t cryptoMode)
00101 {
00102 
00103     switch(cryptoMode) {
00104         case MFST_CRYPT_SHA256:
00105             return (arm_uc_mm_crypto_flags_t) {.hash = 1U};
00106         // case MFST_CRYPT_SHA256_HMAC:
00107         //     return (arm_uc_mm_crypto_flags_t) {.hash = 1, .hmac = 1};
00108         // case MFST_CRYPT_SHA256_HMAC_AES128_PSK:
00109         //     return (arm_uc_mm_crypto_flags_t) {.hash = 1, .hmac = 1, .aes = 1, .psk = 1};
00110         case MFST_CRYPT_SHA256_ECC:
00111             return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .ecc = 1U};
00112         case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00113             return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .ecc = 1U, .aes = 1U, .psk = 1U};
00114     }
00115     return (arm_uc_mm_crypto_flags_t) {.hash = 0};
00116 
00117 }
00118 
00119 /**
00120  * @brief Extracts the hash of a manifest from the manifest wrapper.
00121  * @details This is a utility function that is used to extract the hash of the manifest for signature validation.
00122  *          This function does not perform validation of the hash buffer, so the hash buffer is expected to be populated
00123  *          with a known-good hash buffer. Typically, this buffer will be stack-allocated.
00124  * @param[in]   buffer The manifest to parse
00125  * @param[out]  hash   Output buffer object to fill with the hash
00126  * @return             MFST_ERR_NONE on success, or a parser error code otherwise
00127  */
00128 arm_uc_error_t ARM_UC_mmGetManifestHashFromBin(arm_uc_buffer_t* buffer, arm_uc_buffer_t* hash)
00129 {
00130     const int32_t fieldID = ARM_UC_MM_DER_SIG_HASH;
00131     int rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, hash);
00132     if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
00133     return (arm_uc_error_t){MFST_ERR_NONE};
00134 }
00135 
00136 /**
00137  * Utility function for printing the hex value of a buffer. Used only for debugging.
00138  * @param buf [description]
00139  */
00140 #if 0
00141 static void hexprint_buffer(arm_uc_buffer_t* buf)
00142 {
00143     for (size_t i = 0; i < buf->size; i++)
00144     {
00145         printf("%02x", buf->ptr[i]);
00146     }
00147 }
00148 #endif
00149 
00150 /**
00151  * @brief ARM_UC_mmValidateManifestHash processes a manifest in order to validate its hash
00152  * @details The manifest parser extracts the manifest hash, calculates the hash of the manifest, then compares it to the
00153  *          hash included in the manifest.
00154  *
00155  *          The outer wrapper of the manifest is called a SignedResource. It contains a Resource object and a
00156  *          ResourceSignature object. The Resource object contains a Resource Type identifier, an optional URL, and
00157  *          either a manifest or binary data.
00158  *
00159  *          This function extracts the Resource object and the ResourceSignature object so that the Resource can be
00160  *          hashed and verified against the hash in the ResourceSignature.
00161  *
00162  *          TODO: The dependency on the cryptoMode contained within the manifest will be removed with the change to CMS
00163  *          First, the Resource object is extracted. Next, the cryptoMode is extracted from the Resource object. This
00164  *          requires that the Resource object be a Manifest.
00165  *
00166  * @param[in]  buffer The buffer that contains the manifest to validate
00167  * @retval            MFST_ERR_NONE on success
00168  * @retval            MFST_ERR_CRYPTO_MODE if there is a cryptographic mode error
00169  * @retval            Otherwise, a DER Parser error can be expected
00170  */
00171 arm_uc_error_t ARM_UC_mmValidateManifestHash(arm_uc_buffer_t* buffer)
00172 {
00173     uint8_t localhash[MAX_HASH_BYTES];      ///< An array to store the locally calculated hash
00174     arm_uc_buffer_t local = {               ///< A buffer structure to use for the locally calculated hash
00175         .size_max = MAX_HASH_BYTES,
00176         .size     = 0,
00177         .ptr      = localhash
00178     };
00179     arm_uc_buffer_t remote = {             ///< A buffer for the hash provided in the manifest
00180         .size_max = MAX_HASH_BYTES,
00181         .size     = 0,
00182         .ptr      = NULL
00183     };
00184     arm_uc_buffer_t resource = {            ///< A buffer for the resource (the manifest) that is wrapped by a signature
00185         .size_max = MAX_HASH_BYTES,
00186         .size     = 0,
00187         .ptr      = NULL
00188     };
00189     arm_uc_mdHandle_t hDigest = {0};        ///< This handle is for the digest algorithm
00190     arm_uc_error_t err = {MFST_ERR_NONE};   ///< The return code variable
00191     uint32_t cryptoMode = 0;                ///< A temporary local copy of the crytpoMode
00192     arm_uc_mdType_t mdType = 0;             ///< A type designator for the type of hash in use
00193 
00194     // Extract the "resource" contained in the Signed Resource object
00195     err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_RESOURCE, &resource);
00196     if (!err.error)
00197     {
00198         // Extract the hash from the manifest
00199         err = ARM_UC_mmGetManifestHash(buffer, &remote);
00200     }
00201     if (!err.error)
00202     {
00203         // Extract the cryptographic mode from the manifest
00204         err = ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
00205     }
00206     if (!err.error)
00207     {
00208         // Set the hash type identifier
00209         switch(cryptoMode)
00210         {
00211             case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00212             case MFST_CRYPT_SHA256:
00213             case MFST_CRYPT_SHA256_ECC:
00214                 mdType = ARM_UC_CU_SHA256;
00215                 break;
00216             default:
00217                 err.code = MFST_ERR_CRYPTO_MODE;
00218                 break;
00219         }
00220     }
00221     if (!err.error)
00222     {
00223         // Initialize the message digest API
00224         err = ARM_UC_cryptoHashSetup(&hDigest, mdType);
00225     }
00226     if (!err.error)
00227     {
00228         // NOTE: If a hash accelerator is present on-chip, this could be converted from a blocking call to an
00229         //       asynchronous one.
00230         // Hash the resource
00231         // Keep Coverity quiet - it can't resolve some semantic conditions here.
00232         if ( resource.ptr == NULL ) {
00233             ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00234         } else  {
00235             err = ARM_UC_cryptoHashUpdate(&hDigest, &resource);
00236         }
00237     }
00238     if (!err.error)
00239     {
00240         // Extract the locally calculated hash from the hash API
00241         err = ARM_UC_cryptoHashFinish(&hDigest, &local);
00242     }
00243     if (!err.error)
00244     {
00245         // Check that the hashes match
00246         // Keep Coverity quiet - it can't resolve some semantic conditions here.
00247         if ( remote.ptr == NULL ) {
00248             ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00249         } else if(ARM_UC_BinCompareCT(&local, &remote)) {
00250             ARM_UC_SET_ERROR(err, MFST_ERR_HASH);
00251         }
00252     }
00253     // Explicitly set the manifest manager's no-error code, rather than another module's, which may be present here.
00254     if (!err.error)
00255     {
00256         ARM_UC_SET_ERROR(err, MFST_ERR_NONE);
00257     }
00258     return err;
00259 }
00260 
00261 enum arm_uc_mmCertificateFetchEvents {
00262     ARM_UC_MM_CERTIFICATE_FETCH_UNINIT,
00263     ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS,
00264     ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH,
00265     ARM_UC_MM_CERTIFICATE_FETCH_ERROR,
00266 };
00267 
00268 /**
00269  * @brief Validates one signature of a manifest, once the signing certificate has been found.
00270  * @param  buffer   Holding buffer for the manifest to validate.
00271  * @param  ca       Buffer holding the certificate to use in verification
00272  * @param  sigIndex Index of the manifest signature to verify with this certificate
00273  * @retval          MFST_ERR_DER_FORMAT on parse error
00274  * @retval          MFST_ERR_CERT_INVALID if the certificate is not valid
00275  * @retval          MFST_ERR_INVALID_SIGNATURE if the signature is invalid
00276  * @retval          MFST_ERR_NONE for a valid signature
00277  */
00278 static arm_uc_error_t ARM_UC_mmValidateSignatureCert(arm_uc_buffer_t* buffer, arm_uc_buffer_t* ca, uint32_t sigIndex)
00279 {
00280     const int32_t fieldIDs[] = {ARM_UC_MM_DER_SIG_HASH, ARM_UC_MM_DER_SIG_SIGNATURES};
00281     arm_uc_buffer_t fields[ARRAY_SIZE(fieldIDs)];
00282 
00283     // Get the signature list
00284     int rc = ARM_UC_mmDERGetSignedResourceValues(buffer, ARRAY_SIZE(fieldIDs), fieldIDs, fields);
00285     if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
00286 
00287     // Get the specified signature block
00288     arm_uc_buffer_t sigblock;
00289     rc = ARM_UC_mmDERGetSequenceElement(&fields[1], sigIndex, &sigblock);
00290     if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
00291 
00292     // Load the specified signature out of the signature block
00293     arm_uc_buffer_t sig;
00294     const int32_t sigID = ARM_UC_MM_DER_SIG_SIGNATURE;
00295     rc = ARM_UC_mmDERParseTree(&arm_uc_mmSignatures[0], &sigblock, 1U, &sigID, &sig);
00296     if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
00297 
00298     // Validate the signature
00299     return ARM_UC_verifyPkSignature(ca, &fields[0], &sig);
00300 }
00301 
00302 struct {
00303     arm_uc_mm_validate_signature_context_t* ctx;
00304     arm_uc_callback_t callbackStorage;
00305 } arm_uc_mmSignatureVerificationContext;
00306 
00307 
00308 /**
00309  * @brief Callback function to continue signature verification once the certificate has been found
00310  * @details This function should be called by the certificate lookup function, which is provided by the application.
00311  *          The certificate lookup function should call this callback regardless of success or failure so that errors
00312  *          can be reported correctly.
00313  *
00314  *          Caveats:
00315  *          The certificate supplied here MUST be the same buffer as was provided to the certificate fetch function.
00316  *          The fingerprint supplied here MUST be the same buffer as was provided to the certificate fetch function.
00317  *
00318  *          These requirements are in place to ensure that only one signature verification may be carried out at a time.
00319  *
00320  *          Once the basic checks are performed in the callback, it schedules the manifest manager to execute later.
00321  *
00322  * @param status      Error code provided by the certificat lookup function
00323  * @param certificate Buffer containing the certificate
00324  * @param fingerprint Buffer containing the certificate fingerprint
00325  */
00326 void ARM_UC_mmCertificateCallback(arm_uc_error_t status, const arm_uc_buffer_t* certificate, const arm_uc_buffer_t* fingerprint)
00327 {
00328     uint32_t event = ARM_UC_MM_CERTIFICATE_FETCH_UNINIT;
00329     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
00330     if (status.error == ERR_NONE)
00331     {
00332         // Verify that this is the same buffer as was provided to the certificate fetch function.
00333         if (fingerprint != &arm_uc_mmSignatureVerificationContext.ctx->fingerprint ||
00334             certificate != &arm_uc_mmSignatureVerificationContext.ctx->cert)
00335         {
00336             event = ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH;
00337         }
00338         else
00339         {
00340             event = ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS;
00341         }
00342     }
00343     else
00344     {
00345         // Store the error for later reporting
00346         arm_uc_mmSignatureVerificationContext.ctx->storedError = status;
00347         event = ARM_UC_MM_CERTIFICATE_FETCH_ERROR;
00348     }
00349     // Post the Manifest Manager state machine entry point to the Update Client event queue
00350     UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%lu)\n", __PRETTY_FUNCTION__, event);
00351     ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry, event);
00352 }
00353 
00354 /**
00355  * @brief State machine that controls the verification of signatures.
00356  * @details First, the state machine attempts to fetch the certificate. When the certificate has been fetched,
00357  *          the state machine validates the signature, then alerts the calling application with the result.
00358  *
00359  *
00360  * @param[in]  ctx   Context pointer for the state machine
00361  * @param[in]  event Event to move the state machine forward
00362  * @retval           MFST_ERR_NONE on success
00363  * @retval           MFST_ERR_PENDING when the validation has not completed and is waiting for external input
00364  *                   (e.g. certificate fetching)
00365  * @retval           Another error code otherwise.
00366  */
00367 static arm_uc_error_t ARM_UC_mmValidateSignatureFSM(arm_uc_mm_validate_signature_context_t* ctx, uint32_t event)
00368 {
00369     arm_uc_error_t err = {MFST_ERR_NONE};
00370     enum arm_uc_mm_pk_sig_state oldState;
00371     UC_MMGR_TRACE("%s (%lu)\n", __PRETTY_FUNCTION__, event);
00372     do
00373     {
00374         oldState = ctx->state;
00375         UC_MMGR_TRACE("%s state:%u\n", __PRETTY_FUNCTION__, oldState);
00376         switch(ctx->state)
00377         {
00378             case UCMM_PKSIG_STATE_FIND_CA:
00379                 // Start the search for a certificate
00380                 // This state transitions automatically to UCMM_PKSIG_STATE_FINDING_CA unless there is an error
00381                 err = ARM_UC_certificateFetch(&ctx->cert,
00382                                               &ctx->fingerprint,
00383                                               &ctx->certList,
00384                                               ARM_UC_mmCertificateCallback);
00385                 if (err.error == ERR_NONE || err.code == MFST_ERR_PENDING)
00386                 {
00387                     ctx->state = UCMM_PKSIG_STATE_FINDING_CA;
00388                     err.code = MFST_ERR_PENDING;
00389                 }
00390                 break;
00391             case UCMM_PKSIG_STATE_FINDING_CA:
00392                 // Wait the Certificate fetch to complete. On completion, this state decides what to do with the result.
00393                 switch(event)
00394                 {
00395                     // If the certificate was fetched successfully, proceed to signature verification
00396                     case ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS:
00397                         err.code = MFST_ERR_NONE;
00398                         ctx->state = UCMM_PKSIG_STATE_CHECK;
00399                         break;
00400                     // If an error occured, extract the error.
00401                     case ARM_UC_MM_CERTIFICATE_FETCH_ERROR:
00402                         err = ctx->storedError;
00403                         break;
00404                     // Otherwise, report a bad event.
00405                     case ARM_UC_MM_CERTIFICATE_FETCH_UNINIT:
00406                     case ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH:
00407                     default:
00408                         err.code = MFST_ERR_BAD_EVENT;
00409                         break;
00410                 }
00411                 break;
00412             // Validate the signature
00413             case UCMM_PKSIG_STATE_CHECK:
00414                 err = ARM_UC_mmValidateSignatureCert(ctx->manifest,
00415                     &ctx->cert, ctx->sigIndex);
00416                 if (err.code == MFST_ERR_NONE)
00417                 {
00418                     ctx->state = UCMM_PKSIG_STATE_IDLE;
00419                 }
00420                 break;
00421             case UCMM_PKSIG_STATE_IDLE:
00422                 err.code = MFST_ERR_NONE;
00423                 // The Entry function will report success after this state exits.
00424                 break;
00425             default:
00426                 err = (arm_uc_error_t){MFST_ERR_INVALID_STATE};
00427                 break;
00428         }
00429 
00430     } while (err.code == MFST_ERR_NONE && ctx->state != oldState);
00431     UC_MMGR_TRACE("%s() return code: %c%c:%hu (%s)\n",
00432         __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
00433     return err;
00434 }
00435 /**
00436  * @brief Start signature verification.
00437  * @details This API initiates a signature verification. The actual signature verification is carried out by
00438  *
00439  *
00440  * @param[in]  ctx        Signature validation context. This contains all the state used by the signature validator.
00441  * @param[in]  buffer     A buffer containing the manifest to verify
00442  * @param[in]  certBuffer A temporary storage buffer for certificate fetching
00443  * @param[in]  sigIndex   Index of the signature to verify.
00444  * @retval                MFST_ERR_NONE on success
00445  * @retval                MFST_ERR_PENDING when the validation has not completed and is waiting for external input
00446  *                        (e.g. certificate fetching)
00447  * @retval                Another error code otherwise.
00448  */
00449 arm_uc_error_t ARM_UC_mmValidateSignature(arm_uc_mm_validate_signature_context_t* ctx,
00450                                           void (*applicationEventHandler)(uint32_t),
00451                                           arm_uc_buffer_t* buffer,
00452                                           arm_uc_buffer_t* certBuffer,
00453                                           uint32_t sigIndex)
00454 {
00455     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)sigIndex);
00456     arm_uc_error_t err = {MFST_ERR_NONE};
00457     if (ctx == NULL)
00458     {
00459         ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00460     }
00461     if (err.error == ERR_NONE)
00462     {
00463 #ifdef ATOMIC_QUEUE_CONFIG_ELEMENT_LOCK
00464         arm_uc_mmSignatureVerificationContext.callbackStorage.lock = 0;
00465 #endif
00466         arm_uc_mmSignatureVerificationContext.ctx = ctx;
00467         // Extract the certificate identifier from the manifest
00468         err = ARM_UC_mmGetCertificateId(buffer, sigIndex, &arm_uc_mmSignatureVerificationContext.ctx->fingerprint);
00469         UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", "Get Certificate ID return code:", err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
00470     }
00471     if(err.error == 0 && ctx)
00472     {
00473         // Copy all the relevant inputs into the state variable
00474         err.code = MFST_ERR_NONE;
00475         arm_uc_mmSignatureVerificationContext.ctx->manifest                = buffer;
00476         arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler = applicationEventHandler;
00477         arm_uc_mmSignatureVerificationContext.ctx->state                   = UCMM_PKSIG_STATE_FIND_CA;
00478         arm_uc_mmSignatureVerificationContext.ctx->sigIndex                = sigIndex;
00479         ARM_UC_buffer_shallow_copy(&arm_uc_mmSignatureVerificationContext.ctx->cert, certBuffer);
00480         UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%lu)\n", __PRETTY_FUNCTION__, ARM_UC_MM_EVENT_BEGIN);
00481         ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry, ARM_UC_MM_EVENT_BEGIN);
00482     }
00483     UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
00484     return err;
00485 }
00486 
00487 /**
00488  * @brief Main entry point for callbacks to enter the state machine.
00489  * @details Calls the signature verification state machine. If the result is not Pending, calls the application event
00490  *          handler with a result code.
00491  *          Application event handler is invoked directly, not queued because this function should have minimal stack
00492  *          and it should be called directly from the event queue.
00493  * @param[in] event Event to forward to the state machine
00494  */
00495 void ARM_UC_mmVerifySignatureEntry(uint32_t event)
00496 {
00497     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
00498     arm_uc_error_t err = ARM_UC_mmValidateSignatureFSM(arm_uc_mmSignatureVerificationContext.ctx , event);
00499     if (err.code != MFST_ERR_NONE && err.code != MFST_ERR_PENDING)
00500     {
00501         arm_uc_mmSignatureVerificationContext.ctx->storedError = err;
00502         arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler(ARM_UC_MM_RC_ERROR);
00503     }
00504     if (err.code == MFST_ERR_NONE && arm_uc_mmSignatureVerificationContext.ctx->state == UCMM_PKSIG_STATE_IDLE)
00505     {
00506         // A callback is not posted since this runs inside
00507         arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler(ARM_UC_MM_RC_DONE);
00508     }
00509     UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
00510 }