Simple interface for Mbed Cloud Client

Dependents:  

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