Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

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 #include "update-client-common/arm_uc_config.h"
00025 #include "update-client-metadata-header/arm_uc_buffer_utilities.h"
00026 #include "update-client-control-center/arm_uc_certificate.h"
00027 #include "update-client-control-center/arm_uc_pre_shared_key.h"
00028 
00029 #include "arm_uc_mmDerManifestAccessors.h"
00030 #include "update-client-manifest-manager/update-client-manifest-manager.h"
00031 
00032 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00033 #include "mbedtls/ccm.h"
00034 #endif /* ARM_UC_FEATURE_MANIFEST_PSK */
00035 
00036 #include <string.h>
00037 
00038 extern int ARM_UC_MM_ASN1_get_tag(unsigned char **p,
00039                                   const unsigned char *end,
00040                                   size_t *len, int tag);
00041 
00042 void ARM_UC_mmVerifySignatureEntry(uintptr_t event);
00043 /**
00044  * @file Cryptographic utilities
00045  * This file provides two primary APIs:
00046  * * Verifying manifest hashes
00047  * * Verifying manifest signatures
00048  *
00049  * Some utility functions used by other files in this module are also provided.
00050  *
00051  * Algorithm support:
00052  * ECC is currently supported, but RSA is not.
00053  * Currently, only ECC secp256r1 (prime256v1) is supported.
00054  * Currently, only SHA256 is supported.
00055  * HMAC is not yet supported.
00056  */
00057 
00058 /**
00059  * @brief Returns the sizes of the cryptographic primitives used by the supplied manifest.
00060  * @details Extracts the cryptomode field from a manifest and returns a struct that describes the size of cryptographic
00061  *          primitives used in the manifest. The supplied manifest must have been validated. No validation is performed
00062  *          by this function.
00063  *
00064  * @param[in]  buffer A buffer that contains a validated manifest.
00065  * @return            A struct cryptsize, which contains the AES primitive sizes and SHA primitive size, both in bytes.
00066  *                    An invalid cryptographic mode specifier will cause primitive sizes of `0` to be returned.
00067  */
00068 struct cryptsize getCryptInfo(arm_uc_buffer_t *buffer)
00069 {
00070     struct cryptsize cs = {0};
00071     uint32_t cryptoMode = 1U; // default SHA256 and ECC
00072     ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
00073 
00074     switch (cryptoMode) {
00075 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00076         case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00077             cs.aeslen = 128 / CHAR_BIT;
00078             // fall through
00079             __attribute__((fallthrough)); // prevent fallthrough warning
00080             // case MFST_CRYPT_SHA256_HMAC:
00081 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00082         case MFST_CRYPT_SHA256:
00083             cs.hashlen = 256 / CHAR_BIT;
00084             break;
00085 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00086         case MFST_CRYPT_SHA256_ECC:
00087             cs.hashlen = 256 / CHAR_BIT;
00088             break;
00089 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00090 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00091         case MFST_CRYPT_PSK_AES128CCM_SHA256:
00092         case MFST_CRYPT_NONE_PSK_AES128CCM_SHA256:
00093             cs.aeslen = 128 / CHAR_BIT;
00094             cs.hashlen = 256 / CHAR_BIT;
00095             break;
00096 #endif /* ARM_UC_FEATURE_MANIFEST_PSK */
00097         default:
00098             break;
00099     }
00100     return cs;
00101 }
00102 
00103 /**
00104  * @brief Converts a cryptographic mode enum to a structure with mode identifiers
00105  * @details In order to simplify many tests, the cryptographic mode identifier is converted into a structure of mode
00106  *          identifiers, one for each cryptographic primitive. This allows other parts of the code to examine the mode
00107  *          of one particular primitive without testing against many enums. This function performs no validation. The
00108  *          calling function should have performed validation in advance. If the cryptoMode is unrecognized, then a
00109  *          return will be populated with 0 for every flag.
00110  *
00111  *          HMAC modes are not currently supported.
00112  * TODO: Convert flags to enums
00113  * @param[in]  cryptoMode The cryptographic mode enum that specifies the settings for each primitive
00114  * @return                A structure of flags that indicate the mode of:
00115  *                        * Hash algorithm
00116  *                        * MAC
00117  *                        * Symmetric Encryption
00118  *                        * Pre-shared keys
00119  *                        * Public Key modes
00120  */
00121 arm_uc_mm_crypto_flags_t ARM_UC_mmGetCryptoFlags(uint32_t cryptoMode)
00122 {
00123 
00124     switch (cryptoMode) {
00125         case MFST_CRYPT_SHA256:
00126             return (arm_uc_mm_crypto_flags_t) {.hash = 1U};
00127             // case MFST_CRYPT_SHA256_HMAC:
00128             //     return (arm_uc_mm_crypto_flags_t) {.hash = 1, .hmac = 1};
00129             // case MFST_CRYPT_SHA256_HMAC_AES128_PSK:
00130             //     return (arm_uc_mm_crypto_flags_t) {.hash = 1, .hmac = 1, .aes = 1, .psk = 1};
00131 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00132         case MFST_CRYPT_SHA256_ECC:
00133             return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .ecc = 1U};
00134         case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00135             return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .ecc = 1U, .aes = 1U, .psk = 1U};
00136 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00137 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00138         case MFST_CRYPT_PSK_AES128CCM_SHA256:
00139             return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .aes = 1U, .psk = 1U};
00140         case MFST_CRYPT_NONE_PSK_AES128CCM_SHA256:
00141             return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .psk = 1U};
00142 #endif /* ARM_UC_FEATURE_MANIFEST_PSK */
00143     }
00144     return (arm_uc_mm_crypto_flags_t) {.hash = 0};
00145 
00146 }
00147 
00148 /**
00149  * @brief Extracts the hash of a manifest from the manifest wrapper.
00150  * @details This is a utility function that is used to extract the hash of the manifest for signature validation.
00151  *          This function does not perform validation of the hash buffer, so the hash buffer is expected to be populated
00152  *          with a known-good hash buffer. Typically, this buffer will be stack-allocated.
00153  * @param[in]   buffer The manifest to parse
00154  * @param[out]  hash   Output buffer object to fill with the hash
00155  * @return             ERR_NONE on success, or a parser error code otherwise
00156  */
00157 arm_uc_error_t ARM_UC_mmGetManifestHashFromBin(arm_uc_buffer_t *buffer, arm_uc_buffer_t *hash)
00158 {
00159     const int32_t fieldID = ARM_UC_MM_DER_SIG_HASH;
00160     int rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, hash);
00161     if (rc) return (arm_uc_error_t) {MFST_ERR_DER_FORMAT};
00162     return (arm_uc_error_t) {ERR_NONE};
00163 }
00164 
00165 /**
00166  * Utility function for printing the hex value of a buffer. Used only for debugging.
00167  * @param buf [description]
00168  */
00169 #if 0
00170 static void hexprint_buffer(arm_uc_buffer_t *buf)
00171 {
00172     for (size_t i = 0; i < buf->size; i++) {
00173         printf("%02x", buf->ptr[i]);
00174     }
00175 }
00176 #endif
00177 
00178 /**
00179  * @brief ARM_UC_mmValidateManifestHash processes a manifest in order to validate its hash
00180  * @details The manifest parser extracts the manifest hash, calculates the hash of the manifest, then compares it to the
00181  *          hash included in the manifest.
00182  *
00183  *          The outer wrapper of the manifest is called a SignedResource. It contains a Resource object and a
00184  *          ResourceSignature object. The Resource object contains a Resource Type identifier, an optional URL, and
00185  *          either a manifest or binary data.
00186  *
00187  *          This function extracts the Resource object and the ResourceSignature object so that the Resource can be
00188  *          hashed and verified against the hash in the ResourceSignature.
00189  *
00190  *          TODO: The dependency on the cryptoMode contained within the manifest will be removed with the change to CMS
00191  *          First, the Resource object is extracted. Next, the cryptoMode is extracted from the Resource object. This
00192  *          requires that the Resource object be a Manifest.
00193  *
00194  * @param[in]  buffer The buffer that contains the manifest to validate
00195  * @retval            ERR_NONE on success
00196  * @retval            MFST_ERR_CRYPTO_MODE if there is a cryptographic mode error
00197  * @retval            Otherwise, a DER Parser error can be expected
00198  */
00199 arm_uc_error_t ARM_UC_mmValidateManifestHash(arm_uc_buffer_t *buffer)
00200 {
00201     uint8_t localhash[MAX_HASH_BYTES];      ///< An array to store the locally calculated hash
00202     arm_uc_buffer_t local = {               ///< A buffer structure to use for the locally calculated hash
00203         .size_max = MAX_HASH_BYTES,
00204         .size     = 0,
00205         .ptr      = localhash
00206     };
00207     arm_uc_buffer_t remote = {             ///< A buffer for the hash provided in the manifest
00208         .size_max = MAX_HASH_BYTES,
00209         .size     = 0,
00210         .ptr      = NULL
00211     };
00212     arm_uc_buffer_t resource = {            ///< A buffer for the resource (the manifest) that is wrapped by a signature
00213         .size_max = MAX_HASH_BYTES,
00214         .size     = 0,
00215         .ptr      = NULL
00216     };
00217     arm_uc_mdHandle_t hDigest = {0};        ///< This handle is for the digest algorithm
00218     arm_uc_error_t err = {ERR_NONE};   ///< The return code variable
00219     uint32_t cryptoMode = 0;                ///< A temporary local copy of the crytpoMode
00220     arm_uc_mdType_t mdType = 0;             ///< A type designator for the type of hash in use
00221 
00222     // Extract the "resource" contained in the Signed Resource object
00223     err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_RESOURCE, &resource);
00224     if (!err.error) {
00225         // Extract the hash from the manifest
00226         err = ARM_UC_mmGetManifestHash(buffer, &remote);
00227     }
00228     if (!err.error) {
00229         // Extract the cryptographic mode from the manifest
00230         err = ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
00231     }
00232     if (!err.error) {
00233         // Set the hash type identifier
00234         switch (cryptoMode) {
00235             case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00236             case MFST_CRYPT_SHA256:
00237             case MFST_CRYPT_SHA256_ECC:
00238             case MFST_CRYPT_NONE_PSK_AES128CCM_SHA256:
00239             case MFST_CRYPT_PSK_AES128CCM_SHA256:
00240                 mdType = ARM_UC_CU_SHA256;
00241                 break;
00242             default:
00243                 err.code = MFST_ERR_CRYPTO_MODE;
00244                 break;
00245         }
00246     }
00247     if (!err.error) {
00248         // Initialize the message digest API
00249         err = ARM_UC_cryptoHashSetup(&hDigest, mdType);
00250     }
00251     if (!err.error) {
00252         // NOTE: If a hash accelerator is present on-chip, this could be converted from a blocking call to an
00253         //       asynchronous one.
00254         // Hash the resource
00255         // Keep Coverity quiet - it can't resolve some semantic conditions here.
00256         if (resource.ptr == NULL) {
00257             ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00258         } else  {
00259             err = ARM_UC_cryptoHashUpdate(&hDigest, &resource);
00260         }
00261     }
00262     if (!err.error) {
00263         // Extract the locally calculated hash from the hash API
00264         err = ARM_UC_cryptoHashFinish(&hDigest, &local);
00265     }
00266     if (!err.error) {
00267         // Check that the hashes match
00268         // Keep Coverity quiet - it can't resolve some semantic conditions here.
00269         if (remote.ptr == NULL) {
00270             ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00271         } else if (ARM_UC_BinCompareCT(&local, &remote)) {
00272             ARM_UC_SET_ERROR(err, MFST_ERR_HASH);
00273         }
00274     }
00275     // Explicitly set the manifest manager's no-error code, rather than another module's, which may be present here.
00276     if (!err.error) {
00277         ARM_UC_SET_ERROR(err, ERR_NONE);
00278     }
00279     return err;
00280 }
00281 
00282 enum arm_uc_mmCertificateFetchEvents {
00283     ARM_UC_MM_CERTIFICATE_FETCH_UNINIT,
00284     ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS,
00285     ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH,
00286     ARM_UC_MM_CERTIFICATE_FETCH_ERROR,
00287 };
00288 
00289 /**
00290  * @brief Validates one signature of a manifest, once the signing certificate has been found.
00291  * @param  buffer   Holding buffer for the manifest to validate.
00292  * @param  ca       Buffer holding the certificate to use in verification
00293  * @param  sigIndex Index of the manifest signature to verify with this certificate
00294  * @retval          MFST_ERR_DER_FORMAT on parse error
00295  * @retval          MFST_ERR_CERT_INVALID if the certificate is not valid
00296  * @retval          MFST_ERR_INVALID_SIGNATURE if the signature is invalid
00297  * @retval          ERR_NONE for a valid signature
00298  */
00299 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00300 
00301 #if defined(ARM_UC_FEATURE_CRYPTO_MBEDTLS) && (ARM_UC_FEATURE_CRYPTO_MBEDTLS == 1)
00302 /**
00303  * @brief Verify a public key signature
00304  * @details This function loads a certificate out of `ca`, and validates `hash` using the certificate and `sig`. If the
00305  *          certificate used by this function requires a certificate chain validation (i.e. it is not the root of trust,
00306  *          or it has not been previously validated), certificate chain validation should be done prior to calling this
00307  *          function.
00308  *
00309  * WARNING: this function is to be used only inside a function where its arguments have been error checked.
00310  * WARNING: This is an internal utility function and is not accessible outside of the manifest manager.
00311  *
00312  * @param[in] ca A pointer to a buffer that contains the signing certificate.
00313  * @param[in] hash A pointer to a buffer containing the hash to verify.
00314  * @param[in] sig A pointer to a buffer containing a signature by `ca`
00315  * @retval MFST_ERR_CERT_INVALID when the certificate fails to load
00316  * @retval MFST_ERR_INVALID_SIGNATURE when signature verification fails
00317  * @retval ERR_OUT_OF_MEMORY when run out of memory
00318  * @retval ERR_NONE for a valid signature
00319  */
00320 static arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t *ca, const arm_uc_buffer_t *hash,
00321                                         const arm_uc_buffer_t *sig)
00322 {
00323     arm_uc_error_t err = {ERR_NONE};
00324     mbedtls_x509_crt crt;
00325     mbedtls_x509_crt_init(&crt);
00326     int rc = mbedtls_x509_crt_parse_der(&crt, ca->ptr, ca->size);
00327     if (rc == MBEDTLS_ERR_X509_ALLOC_FAILED) {
00328         err.code = ERR_OUT_OF_MEMORY;
00329     } else if (rc < 0) {
00330         UC_MMGR_ERR_MSG("mbedtls_x509_crt_parse_der returned error "PRIu32,  rc);
00331         err.code = MFST_ERR_CERT_INVALID;
00332     } else {
00333         rc = mbedtls_pk_verify(&crt.pk, MBEDTLS_MD_SHA256, hash->ptr, hash->size, sig->ptr, sig->size);
00334         if (rc < 0) {
00335             UC_MMGR_ERR_MSG("mbedtls_pk_verify returned error "PRIu32,  rc);
00336             err.code = MFST_ERR_INVALID_SIGNATURE;
00337         }
00338     }
00339     return err;
00340 }
00341 #elif defined(ARM_UC_FEATURE_CRYPTO_PAL) && (ARM_UC_FEATURE_CRYPTO_PAL == 1)
00342 
00343 arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t *ca, const arm_uc_buffer_t *hash,
00344                                         const arm_uc_buffer_t *sig)
00345 {
00346     arm_uc_error_t err = {MFST_ERR_CERT_INVALID};
00347     palX509Handle_t x509Cert;
00348     palStatus_t status = pal_x509Initiate(&x509Cert);
00349     if (PAL_SUCCESS == status) {
00350         err.code = MFST_ERR_CERT_INVALID;
00351         if (PAL_SUCCESS == pal_x509CertParse(x509Cert, ca->ptr, ca->size)) {
00352             // if (PAL_SUCCESS == pal_x509CertVerify(x509Cert, palX509Handle_t x509CertChain))
00353             // {
00354             err.code = MFST_ERR_INVALID_SIGNATURE;
00355             status = pal_verifySignature(x509Cert, PAL_SHA256, hash->ptr, hash->size, sig->ptr, sig->size);
00356             if (PAL_SUCCESS == status) {
00357                 err.code = ERR_NONE;
00358             } else if (PAL_ERR_CRYPTO_ALLOC_FAILED == status) {
00359                 err.code = ERR_OUT_OF_MEMORY;
00360             } else {
00361                 UC_MMGR_ERR_MSG("pal_verifySignature returned error "PRIu32,  status);
00362             }
00363             // }
00364         }
00365         pal_x509Free(&x509Cert);
00366     } else if (PAL_ERR_CREATION_FAILED  == status) {
00367         err.code = ERR_OUT_OF_MEMORY;
00368     }
00369     return err;
00370 }
00371 #endif
00372 
00373 static arm_uc_error_t ARM_UC_mmValidateSignatureCert(arm_uc_buffer_t *buffer, arm_uc_buffer_t *ca, uint32_t sigIndex)
00374 {
00375     const int32_t fieldIDs[] = {ARM_UC_MM_DER_SIG_HASH, ARM_UC_MM_DER_SIG_SIGNATURES};
00376     arm_uc_buffer_t fields[ARRAY_SIZE(fieldIDs)];
00377 
00378     // Get the signature list
00379     int rc = ARM_UC_mmDERGetSignedResourceValues(buffer, ARRAY_SIZE(fieldIDs), fieldIDs, fields);
00380     if (rc) return (arm_uc_error_t) {MFST_ERR_DER_FORMAT};
00381 
00382     // Get the specified signature block
00383     arm_uc_buffer_t sigblock;
00384     rc = ARM_UC_mmDERGetSequenceElement(&fields[1], sigIndex, &sigblock);
00385     if (rc) return (arm_uc_error_t) {MFST_ERR_DER_FORMAT};
00386 
00387     // Load the specified signature out of the signature block
00388     arm_uc_buffer_t sig;
00389     const int32_t sigID = ARM_UC_MM_DER_SIG_SIGNATURE;
00390     rc = ARM_UC_mmDERParseTree(&arm_uc_mmSignatures[0], &sigblock, 1U, &sigID, &sig);
00391     if (rc) return (arm_uc_error_t) {MFST_ERR_DER_FORMAT};
00392 
00393     // Validate the signature
00394     return ARM_UC_verifyPkSignature(ca, &fields[0], &sig);
00395 }
00396 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00397 struct {
00398     arm_uc_mm_validate_signature_context_t *ctx;
00399     arm_uc_callback_t callbackStorage;
00400 } arm_uc_mmSignatureVerificationContext;
00401 
00402 
00403 /**
00404  * @brief Callback function to continue signature verification once the certificate has been found
00405  * @details This function should be called by the certificate lookup function, which is provided by the application.
00406  *          The certificate lookup function should call this callback regardless of success or failure so that errors
00407  *          can be reported correctly.
00408  *
00409  *          Caveats:
00410  *          The certificate supplied here MUST be the same buffer as was provided to the certificate fetch function.
00411  *          The fingerprint supplied here MUST be the same buffer as was provided to the certificate fetch function.
00412  *
00413  *          These requirements are in place to ensure that only one signature verification may be carried out at a time.
00414  *
00415  *          Once the basic checks are performed in the callback, it schedules the manifest manager to execute later.
00416  *
00417  * @param status      Error code provided by the certificat lookup function
00418  * @param certificate Buffer containing the certificate
00419  * @param fingerprint Buffer containing the certificate fingerprint
00420  */
00421 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00422 void ARM_UC_mmCertificateCallback(arm_uc_error_t status, const arm_uc_buffer_t *certificate,
00423                                   const arm_uc_buffer_t *fingerprint)
00424 {
00425     uint32_t event = ARM_UC_MM_CERTIFICATE_FETCH_UNINIT;
00426     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
00427     if (status.error == ERR_NONE) {
00428         // Verify that this is the same buffer as was provided to the certificate fetch function.
00429         if (fingerprint != &arm_uc_mmSignatureVerificationContext.ctx->fingerprint ||
00430                 certificate != &arm_uc_mmSignatureVerificationContext.ctx->cert) {
00431             event = ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH;
00432         } else {
00433             event = ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS;
00434         }
00435     } else {
00436         // Store the error for later reporting
00437         arm_uc_mmSignatureVerificationContext.ctx->storedError = status;
00438         event = ARM_UC_MM_CERTIFICATE_FETCH_ERROR;
00439     }
00440     // Post the Manifest Manager state machine entry point to the Update Client event queue
00441     UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%" PRIu32 ")\n", __PRETTY_FUNCTION__, event);
00442     ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry, event);
00443 }
00444 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00445 /**
00446  * @brief State machine that controls the verification of signatures.
00447  * @details First, the state machine attempts to fetch the certificate. When the certificate has been fetched,
00448  *          the state machine validates the signature, then alerts the calling application with the result.
00449  *
00450  *
00451  * @param[in]  ctx   Context pointer for the state machine
00452  * @param[in]  event Event to move the state machine forward
00453  * @retval           ERR_NONE on success
00454  * @retval           MFST_ERR_PENDING when the validation has not completed and is waiting for external input
00455  *                   (e.g. certificate fetching)
00456  * @retval           Another error code otherwise.
00457  */
00458 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00459 static arm_uc_error_t ARM_UC_mmValidateSignatureFSM(arm_uc_mm_validate_signature_context_t *ctx, uint32_t event)
00460 {
00461     arm_uc_error_t err = {ERR_NONE};
00462     enum arm_uc_mm_pk_sig_state oldState;
00463     UC_MMGR_TRACE("%s (%" PRIu32 ")\n", __PRETTY_FUNCTION__, event);
00464     do {
00465         oldState = ctx->pk_state;
00466         UC_MMGR_TRACE("%s state:%u\n", __PRETTY_FUNCTION__, oldState);
00467         switch (ctx->pk_state) {
00468             case UCMM_PKSIG_STATE_FIND_CA:
00469                 // Start the search for a certificate
00470                 // This state transitions automatically to UCMM_PKSIG_STATE_FINDING_CA unless there is an error
00471                 err = ARM_UC_certificateFetch(&ctx->cert,
00472                                               &ctx->fingerprint,
00473                                               &ctx->certList,
00474                                               ARM_UC_mmCertificateCallback);
00475                 if (err.error == ERR_NONE || err.code == MFST_ERR_PENDING) {
00476                     ctx->pk_state = UCMM_PKSIG_STATE_FINDING_CA;
00477                     err.code = MFST_ERR_PENDING;
00478                 }
00479                 break;
00480             case UCMM_PKSIG_STATE_FINDING_CA:
00481                 // Wait the Certificate fetch to complete. On completion, this state decides what to do with the result.
00482                 switch (event) {
00483                     // If the certificate was fetched successfully, proceed to signature verification
00484                     case ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS:
00485                         err.code = ERR_NONE;
00486                         ctx->pk_state = UCMM_PKSIG_STATE_CHECK;
00487                         break;
00488                     // If an error occured, extract the error.
00489                     case ARM_UC_MM_CERTIFICATE_FETCH_ERROR:
00490                         err = ctx->storedError;
00491                         break;
00492                     // Otherwise, report a bad event.
00493                     case ARM_UC_MM_CERTIFICATE_FETCH_UNINIT:
00494                     case ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH:
00495                     default:
00496                         err.code = MFST_ERR_BAD_EVENT;
00497                         break;
00498                 }
00499                 break;
00500             // Validate the signature
00501             case UCMM_PKSIG_STATE_CHECK:
00502                 err = ARM_UC_mmValidateSignatureCert(ctx->manifest,
00503                                                      &ctx->cert, ctx->sigIndex);
00504                 if (err.code == ERR_NONE) {
00505                     ctx->pk_state = UCMM_PKSIG_STATE_IDLE;
00506                 }
00507                 break;
00508             case UCMM_PKSIG_STATE_IDLE:
00509                 err.code = ERR_NONE;
00510                 // The Entry function will report success after this state exits.
00511                 break;
00512             default:
00513                 err = (arm_uc_error_t) {MFST_ERR_INVALID_STATE};
00514                 break;
00515         }
00516 
00517     } while (err.code == ERR_NONE && ctx->pk_state != oldState);
00518     UC_MMGR_TRACE("%s() return code: %c%c:%hu (%s)\n",
00519                   __PRETTY_FUNCTION__, CC_ASCII(err.modulecc[0]), CC_ASCII(err.modulecc[1]),
00520                   err.error, ARM_UC_err2Str(err));
00521     return err;
00522 }
00523 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00524 
00525 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00526 static arm_uc_error_t ARM_UC_mmValidateSignaturePSKFSM(arm_uc_mm_validate_signature_context_t *ctx, uint32_t event)
00527 {
00528     arm_uc_error_t err = {ERR_NONE};
00529     enum arm_uc_mm_psk_sig_state oldState;
00530     UC_MMGR_TRACE("%s (%" PRIu32 ")\n", __PRETTY_FUNCTION__, event);
00531     do {
00532         oldState = ctx->psk_state;
00533         UC_MMGR_TRACE("%s state:%u\n", __PRETTY_FUNCTION__, oldState);
00534         switch (ctx->psk_state) {
00535             case ARM_UC_MM_PSKSIG_STATE_FIND_PSK:
00536                 // Start the search for a PSK
00537                 // This state transitions automatically to UCMM_PKSIG_STATE_FINDING_CA unless there is an error
00538                 err = ARM_UC_PreSharedKey_GetSecret((const uint8_t **)&ctx->PSK.ptr, 128);
00539                 if (err.error == ERR_NONE) {
00540                     ctx->PSK.size = 128 / 8;
00541                     ctx->PSK.size_max = 128 / 8;
00542                     ctx->psk_state = ARM_UC_MM_PSKSIG_STATE_FIND_SIG_START;
00543                 }
00544                 break;
00545             // TODO: Currently, PSK ID is unused.
00546             case ARM_UC_MM_PSKSIG_STATE_FIND_SIG_START: {
00547                 // Right now, only "thismessage://" URIs are supported.
00548                 const char refPrefix[] = "thismessage://";
00549                 // The following line deliberately excludes a ' - 1' because the URI needs to have
00550                 // exactly one character following the "thismessage://"
00551                 err.code = ERR_NONE;
00552                 int sizeOK = ctx->keyTableRef.size == sizeof(refPrefix);
00553                 int matchOK = 0;
00554                 if (sizeOK) {
00555                     matchOK = 1;
00556                     // NOTE: There seems to be a problem with the evaluation of strncmp and/or memcmp on these values.
00557                     // Byte-by-byte comparison *does* work. This should be investigated.
00558                     for (size_t i = 0; i < sizeof(refPrefix) - 1; i++) {
00559                         if (ctx->keyTableRef.ptr[i] != refPrefix[i]) {
00560                             matchOK = 0;
00561                             break;
00562                         }
00563                     }
00564                 } else {
00565                     UC_MMGR_TRACE("keytable reference length: expected=%" PRIu16 " actual=%" PRIu32 "\n", (uint16_t)sizeof(refPrefix),
00566                                   ctx->keyTableRef.size);
00567                 }
00568                 if (!matchOK) {
00569                     UC_MMGR_TRACE("KeyTable Error - not matched.");
00570                     ARM_UC_SET_ERROR(err, MFST_ERR_BAD_KEYTABLE);
00571                 }
00572                 // Only position 1 is supported for now. Position 0 is the manifest
00573                 // Check the signature location
00574                 if (err.error == ERR_NONE && ctx->keyTableRef.ptr[sizeof(refPrefix) - 1] != '1') {
00575                     ARM_UC_SET_ERROR(err, MFST_ERR_MISSING_KEYTABLE);
00576                 }
00577 
00578                 uint8_t *p = ctx->manifest->ptr;
00579                 uint8_t *end = p + ctx->manifest->size;
00580                 size_t len = 0;
00581                 // Get the signature
00582                 if (err.error == ERR_NONE) {
00583                     // To get the signature, we have to find out how big the manifest is.
00584                     int rc = ARM_UC_MM_ASN1_get_tag(&p, end, &len, ARM_UC_MM_ASN1_SEQUENCE | ARM_UC_MM_ASN1_CONSTRUCTED);
00585                     if (rc) {
00586                         UC_MMGR_TRACE("KeyTable Error - get-tag failed, manifest length == %" PRIu32, len);
00587                         ARM_UC_SET_ERROR(err, MFST_ERR_MISSING_KEYTABLE);
00588                     }
00589                 }
00590                 if (err.error == ERR_NONE) {
00591                     p += len;
00592                     len = 0;
00593                     // Now, read the content. Currently, a single binary string is expected.
00594                     int rc = ARM_UC_MM_ASN1_get_tag(&p, end, &len, ARM_UC_MM_ASN1_OCTET_STRING);
00595                     if (rc || (len == 0)) {
00596                         UC_MMGR_TRACE("KeyTable Error - get-content failed, keytable length == %" PRIu32, len);
00597                         ARM_UC_SET_ERROR(err, len == 0 ? MFST_ERR_MISSING_KEYTABLE : MFST_ERR_BAD_KEYTABLE);
00598                     }
00599                 }
00600                 if (err.error == ERR_NONE) {
00601                     UC_MMGR_TRACE("KeyTable Found");
00602                     ctx->cipherText.ptr = p;
00603                     ctx->cipherText.size = len;
00604                     ctx->cipherText.size_max = len;
00605                     ctx->psk_state = ARM_UC_MM_PSKSIG_STATE_VERIFY;
00606                 }
00607                 break;
00608             }
00609             case ARM_UC_MM_PSKSIG_STATE_FIND_SIG:
00610                 // Wait for the find-sig to end
00611                 // This is currently disabled.
00612                 break;
00613             // Validate the signature
00614             case ARM_UC_MM_PSKSIG_STATE_VERIFY: {
00615                 err.code = ERR_NONE;
00616                 UC_MMGR_TRACE("Beginning PSK signature verification");
00617                 mbedtls_ccm_context ccm_ctx;
00618                 mbedtls_ccm_init(&ccm_ctx);
00619                 int rc = mbedtls_ccm_setkey(&ccm_ctx, MBEDTLS_CIPHER_ID_AES, ctx->PSK.ptr, 8 * ctx->PSK.size);
00620                 if (rc) {
00621                     UC_MMGR_TRACE("mbedtls_ccm_setkey failed with %d", rc);
00622                     ARM_UC_SET_ERROR(err, (TWO_CC('M', 'T') << 16) + ((-rc) & 0xFFFF));
00623                 }
00624 
00625                 size_t tagSize = 0;
00626                 switch (ctx->encryptionMode) {
00627                     case MFST_CRYPT_NONE_PSK_AES128CCM_SHA256:
00628                     case MFST_CRYPT_PSK_AES128CCM_SHA256:
00629                         tagSize = 128 / 8;
00630                         break;
00631                 }
00632 
00633 
00634                 uint8_t plaintextBuffer[ARM_UC_SHA512_SIZE + ARM_UC_AES256_KEY_SIZE + 6];
00635                 // Decrypt the key payload
00636                 if (err.error == ERR_NONE) {
00637                     size_t cipherTextSize = ctx->cipherText.size - tagSize;
00638                     uint8_t *tagPtr = ctx->cipherText.ptr + cipherTextSize;
00639 
00640                     UC_MMGR_TRACE("Attempting authenticated decryption of manifest hash");
00641                     rc = mbedtls_ccm_auth_decrypt(
00642                              &ccm_ctx,                       // Cipher context
00643                              cipherTextSize, // Input size (without tag)
00644                              ctx->keyTableIV.ptr,            // Init vector
00645                              ctx->keyTableIV.size,           // Size of the init vector
00646                              NULL,                           // Authenticated Associated Data
00647                              0,                              // AAD length
00648                              ctx->cipherText.ptr,
00649                              plaintextBuffer,
00650                              tagPtr,
00651                              tagSize);                       //
00652 
00653                     if (rc == MBEDTLS_ERR_CCM_AUTH_FAILED) {
00654                         ARM_UC_SET_ERROR(err, MFST_ERR_INVALID_SIGNATURE);
00655                     } else if (rc) {
00656                         UC_MMGR_TRACE("mbedtls_ccm_auth_decrypt failed with %d", rc);
00657                         ARM_UC_SET_ERROR(err, (TWO_CC('M', 'T') << 16) + ((-rc) & 0xFFFF));
00658                     }
00659                 }
00660                 arm_uc_buffer_t fields[2];
00661                 if (err.error == ERR_NONE) {
00662                     arm_uc_buffer_t buf = {
00663                         .size_max = sizeof(plaintextBuffer),
00664                         .size = ctx->cipherText.size - tagSize,
00665                         .ptr = plaintextBuffer
00666                     };
00667                     const int32_t fieldIDs[] = {
00668                         ARM_UC_MM_KT_HASH,
00669                         ARM_UC_MM_KT_PAYLOAD_KEY,
00670                     };
00671                     const size_t nfields = sizeof(fieldIDs) / sizeof(fieldIDs[0]);
00672                     UC_MMGR_TRACE("Extracting manifest hash and payload key");
00673                     // Extract the manifest hash and payload key
00674                     rc = ARM_UC_mmDERParseTree(
00675                              arm_uc_mmKeyTableEntry,
00676                              &buf, nfields, fieldIDs, fields
00677                          );
00678                     if (rc == 1 && ctx->encryptionMode == MFST_CRYPT_NONE_PSK_AES128CCM_SHA256) {
00679                         rc = 0;
00680                     }
00681                     if (rc) {
00682                         UC_MMGR_TRACE("ARM_UC_mmDERParseTree failed with %d", rc);
00683                         ARM_UC_SET_ERROR(err, MFST_ERR_DER_FORMAT);
00684                     }
00685                 }
00686                 arm_uc_buffer_t remoteDigest;
00687                 if (err.error == ERR_NONE) {
00688                     UC_MMGR_TRACE("Load manifest hash from manifest signature");
00689                     err = ARM_UC_mmGetManifestHash(ctx->manifest, &remoteDigest);
00690                 }
00691                 if (err.error == ERR_NONE) {
00692                     UC_MMGR_TRACE("Comparing manifest hash and authenticated hash");
00693                     rc = ARM_UC_BinCompareCT(&fields[0], &remoteDigest);
00694                     if (rc) {
00695                         UC_MMGR_TRACE("Manifest hash does not match authenticated hash");
00696                         ARM_UC_SET_ERROR(err, MFST_ERR_INVALID_SIGNATURE);
00697                     }
00698                 }
00699                 if (err.error == ERR_NONE) {
00700                     ARM_UC_SET_ERROR(err, ERR_NONE);
00701                     ctx->psk_state = ARM_UC_MM_PSKSIG_STATE_IDLE;
00702                 }
00703                 break;
00704             }
00705             case ARM_UC_MM_PSKSIG_STATE_IDLE:
00706                 ARM_UC_SET_ERROR(err, ERR_NONE);
00707                 // The Entry function will report success after this state exits.
00708                 break;
00709             default:
00710                 err = (arm_uc_error_t) {MFST_ERR_INVALID_STATE};
00711                 break;
00712         }
00713     } while (err.error == ERR_NONE && ctx->psk_state != oldState);
00714     UC_MMGR_TRACE("%s() return code: %c%c:%hu (%s)\n",
00715                   __PRETTY_FUNCTION__, CC_ASCII(err.modulecc[0]), CC_ASCII(err.modulecc[1]),
00716                   err.error, ARM_UC_err2Str(err));
00717     return err;
00718 }
00719 #endif /* ARM_UC_FEATURE_MANIFEST_PSK */
00720 /**
00721  * @brief Start signature verification.
00722  * @details This API initiates a signature verification. The actual signature verification is carried out by
00723  *
00724  *
00725  * @param[in]  ctx        Signature validation context. This contains all the state used by the signature validator.
00726  * @param[in]  buffer     A buffer containing the manifest to verify
00727  * @param[in]  certBuffer A temporary storage buffer for certificate fetching
00728  * @param[in]  sigIndex   Index of the signature to verify.
00729  * @retval                ERR_NONE on success
00730  * @retval                MFST_ERR_PENDING when the validation has not completed and is waiting for external input
00731  *                        (e.g. certificate fetching)
00732  * @retval                Another error code otherwise.
00733  */
00734 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00735 arm_uc_error_t ARM_UC_mmValidateSignature(arm_uc_mm_validate_signature_context_t *ctx,
00736                                           void (*applicationEventHandler)(uintptr_t),
00737                                           arm_uc_buffer_t *buffer,
00738                                           arm_uc_buffer_t *certBuffer,
00739                                           uint32_t sigIndex)
00740 {
00741     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)sigIndex);
00742     arm_uc_error_t err = {ERR_NONE};
00743     if (ctx == NULL) {
00744         ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00745     }
00746     if (err.error == ERR_NONE) {
00747         err = ARM_UC_mmGetCryptoMode(buffer, &ctx->encryptionMode);
00748     }
00749     if (err.error == ERR_NONE) {
00750 #ifdef ATOMIC_QUEUE_CONFIG_ELEMENT_LOCK
00751         arm_uc_mmSignatureVerificationContext.callbackStorage.lock = 0;
00752 #endif
00753         arm_uc_mmSignatureVerificationContext.ctx = ctx;
00754         // Extract the certificate identifier from the manifest
00755         err = ARM_UC_mmGetCertificateId(buffer, sigIndex, &arm_uc_mmSignatureVerificationContext.ctx->fingerprint);
00756         UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", "Get Certificate ID return code:",
00757                       CC_ASCII(err.modulecc[0]), CC_ASCII(err.modulecc[1]),
00758                       err.error, ARM_UC_err2Str(err));
00759     }
00760     if (err.error == 0 && ctx) {
00761         // Copy all the relevant inputs into the state variable
00762         err.code = ERR_NONE;
00763         arm_uc_mmSignatureVerificationContext.ctx->manifest                = buffer;
00764         arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler = applicationEventHandler;
00765         arm_uc_mmSignatureVerificationContext.ctx->pk_state                = UCMM_PKSIG_STATE_FIND_CA;
00766         arm_uc_mmSignatureVerificationContext.ctx->sigIndex                = sigIndex;
00767         ARM_UC_buffer_shallow_copy(&arm_uc_mmSignatureVerificationContext.ctx->cert, certBuffer);
00768         UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%" PRIi16 ")\n", __PRETTY_FUNCTION__, ARM_UC_MM_EVENT_BEGIN);
00769         ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry,
00770                             ARM_UC_MM_EVENT_BEGIN);
00771     }
00772     UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__,
00773                   CC_ASCII(err.modulecc[0]), CC_ASCII(err.modulecc[1]), err.error, ARM_UC_err2Str(err));
00774     return err;
00775 }
00776 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00777 /**
00778  * @brief Main entry point for callbacks to enter the state machine.
00779  * @details Calls the signature verification state machine. If the result is not Pending, calls the application event
00780  *          handler with a result code.
00781  *          Application event handler is invoked directly, not queued because this function should have minimal stack
00782  *          and it should be called directly from the event queue.
00783  * @param[in] event Event to forward to the state machine
00784  */
00785 void ARM_UC_mmVerifySignatureEntry(uintptr_t event)
00786 {
00787     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
00788     arm_uc_error_t err = {MFST_ERR_CRYPTO_MODE};
00789     switch (arm_uc_mmSignatureVerificationContext.ctx->encryptionMode) {
00790 #if defined(ARM_UC_FEATURE_MANIFEST_PUBKEY) && (ARM_UC_FEATURE_MANIFEST_PUBKEY == 1)
00791         case MFST_CRYPT_SHA256_ECC_AES128_PSK:
00792         case MFST_CRYPT_SHA256_ECC:
00793             err = ARM_UC_mmValidateSignatureFSM(arm_uc_mmSignatureVerificationContext.ctx, event);
00794             break;
00795 #endif /* ARM_UC_FEATURE_MANIFEST_PUBKEY */
00796 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00797         case MFST_CRYPT_PSK_AES128CCM_SHA256:
00798         case MFST_CRYPT_NONE_PSK_AES128CCM_SHA256:
00799             err = ARM_UC_mmValidateSignaturePSKFSM(arm_uc_mmSignatureVerificationContext.ctx, event);
00800             break;
00801 #endif /* ARM_UC_FEATURE_MANIFEST_PSK */
00802     }
00803 
00804     if (err.code != ERR_NONE && err.code != MFST_ERR_PENDING) {
00805         arm_uc_mmSignatureVerificationContext.ctx->storedError = err;
00806         arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler(ARM_UC_MM_RC_ERROR);
00807     }
00808     if (err.code == ERR_NONE && arm_uc_mmSignatureVerificationContext.ctx->pk_state == UCMM_PKSIG_STATE_IDLE) {
00809         // A callback is not posted since this runs inside the scheduler
00810         arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler(ARM_UC_MM_RC_DONE);
00811     }
00812     UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__,
00813                   CC_ASCII(err.modulecc[0]), CC_ASCII(err.modulecc[1]), err.error, ARM_UC_err2Str(err));
00814 }
00815 
00816 #if defined(ARM_UC_FEATURE_MANIFEST_PSK) && (ARM_UC_FEATURE_MANIFEST_PSK == 1)
00817 arm_uc_error_t ARM_UC_mmVerifySignaturePSK(arm_uc_mm_validate_signature_context_t *ctx,
00818                                            void (*applicationEventHandler)(uintptr_t),
00819                                            arm_uc_buffer_t *buffer,
00820                                            uint32_t sigIndex)
00821 {
00822     UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)sigIndex);
00823     arm_uc_error_t err = {ERR_NONE};
00824     // Parse the manifest for the hash, the signature (PSK IV) and the certificate list
00825     arm_uc_buffer_t mac;
00826     arm_uc_buffer_t fields[3] = {0};
00827     const int32_t ResourceSignatureIDs[] = {
00828         ARM_UC_MM_DER_MFST_ENC_ENUM,
00829         ARM_UC_MM_DER_SIG_MACS,
00830     };
00831     const int32_t MacBlockIDs[] = {
00832         ARM_UC_MM_DER_SIG_MAC_PSKID,
00833         ARM_UC_MM_DER_SIG_MAC_KEYTABLE_IV,
00834         ARM_UC_MM_DER_SIG_MAC_KEYTABLE_REF,
00835     };
00836     // ctx validity check
00837     if (ctx == NULL) {
00838         ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
00839     } else {
00840         arm_uc_mmSignatureVerificationContext.ctx = ctx;
00841     }
00842     if (err.error == ERR_NONE) {
00843         // Get the content of the ResourceSignature.
00844         int rc = ARM_UC_mmDERGetSignedResourceValues(buffer,
00845                                                      sizeof(ResourceSignatureIDs) / sizeof(ResourceSignatureIDs[0]),
00846                                                      ResourceSignatureIDs,
00847                                                      fields);
00848         if (rc) {
00849             ARM_UC_SET_ERROR(err, MFST_ERR_DER_FORMAT);
00850         }
00851     }
00852     if (err.error == ERR_NONE) {
00853         ctx->encryptionMode = ARM_UC_mmDerBuf2Uint(&fields[0]);
00854         int rc = ARM_UC_mmDERGetSequenceElement(&fields[1], sigIndex, &mac);
00855         if (rc) {
00856             ARM_UC_SET_ERROR(err, MFST_ERR_DER_FORMAT);
00857         }
00858         if (mac.ptr == NULL) {
00859             ARM_UC_SET_ERROR(err, ARM_UC_DP_ERR_NO_MORE_ELEMENTS);
00860         }
00861     }
00862     if (err.error == ERR_NONE) {
00863         // Extract the MAC parameters
00864         int rc = ARM_UC_mmDERParseTree(&arm_uc_mmMacs[0],
00865                                        &mac,
00866                                        sizeof(MacBlockIDs) / sizeof(MacBlockIDs[0]),
00867                                        MacBlockIDs,
00868                                        fields);
00869         if (rc) {
00870             ARM_UC_SET_ERROR(err, MFST_ERR_DER_FORMAT);
00871         }
00872     }
00873     if (err.error == ERR_NONE) {
00874         ARM_UC_buffer_shallow_copy(&ctx->PSKid, &fields[0]);
00875         ARM_UC_buffer_shallow_copy(&ctx->keyTableIV, &fields[1]);
00876         ARM_UC_buffer_shallow_copy(&ctx->keyTableRef, &fields[2]);
00877         if (ctx->keyTableRef.size == 0) {
00878             ARM_UC_SET_ERROR(err, MFST_ERR_MISSING_KEYTABLE);
00879         } else if (ctx->keyTableIV.size < 7 || ctx->keyTableIV.size > 13) {
00880             ARM_UC_SET_ERROR(err, MFST_ERR_CTR_IV_SIZE);
00881         }
00882     }
00883     if (err.error == ERR_NONE && ctx) {
00884         // Copy all the relevant inputs into the state variable
00885         err.code = ERR_NONE;
00886         ctx->manifest                = buffer;
00887         ctx->applicationEventHandler = applicationEventHandler;
00888         ctx->psk_state                   = ARM_UC_MM_PSKSIG_STATE_FIND_PSK;
00889         ctx->sigIndex                = sigIndex;
00890         UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%d)\n", __PRETTY_FUNCTION__, ARM_UC_MM_EVENT_BEGIN);
00891         int rc = ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry,
00892                                      ARM_UC_MM_EVENT_BEGIN);
00893         if (!rc) {
00894             ARM_UC_SET_ERROR(err, MFST_ERR_NOT_READY);
00895         }
00896     }
00897     UC_MMGR_TRACE("< %s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__,
00898                   CC_ASCII(err.modulecc[0]), CC_ASCII(err.modulecc[1]), err.error, ARM_UC_err2Str(err));
00899     return err;
00900 }
00901 #endif /* ARM_UC_FEATURE_MANIFEST_PSK */