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_mmDerManifestParser.c Source File

arm_uc_mmDerManifestParser.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_mmDerManifestParser.h"
00020 
00021 #include <stdio.h>
00022 
00023 #define DER_MANDATORY 0
00024 #define DER_OPTIONAL 1
00025 
00026 #define ARM_UC_MM_DER_ELEMENT_INIT(ID, TAG, OPT, CHILDREN)\
00027     {.id = (ID), .subElements = (CHILDREN), .tag = (TAG), .optional = (OPT), .nSubElements = sizeof(CHILDREN)/sizeof(struct arm_uc_mmDerElement)}
00028 #define ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ID, TAG, OPT)\
00029     {.id = (ID), .subElements = NULL, .tag = (TAG), .optional = (OPT), .nSubElements = 0}
00030 
00031 
00032 /**
00033  * @brief Descriptor for the apply period of a manifest.
00034  *
00035  * applyPeriod SEQUENCE {
00036  *     validFrom     INTEGER,
00037  *     validTo       INTEGER
00038  * }
00039  */
00040 static const struct arm_uc_mmDerElement ManifestApplyPeriod[] =
00041 {
00042     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VALID_FROM, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
00043     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VALID_TO, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
00044 };
00045 /**
00046  * @brief Descriptor of the encryptionMode
00047  *
00048  * encryptionMode  CHOICE {
00049  *     enum    ENUMERATED {
00050  *         invalid(0),
00051  *         aes-128-ctr-ecc-secp256r1-sha256(1),
00052  *         none-ecc-secp256r1-sha256(2),
00053  *         none-none-sha256(3)
00054  *     },
00055  *     objectId    OBJECT IDENTIFIER
00056  * }
00057  */
00058 static const struct arm_uc_mmDerElement encryptionModeChoice[] =
00059 {
00060     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_ENC_ENUM, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
00061     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_ENC_OID, ARM_UC_MM_ASN1_OID, DER_MANDATORY),
00062 };
00063 /**
00064  * @brief Descriptor for resource aliases
00065  *
00066  * ResourceAlias ::= SEQUENCE {
00067  *     hash        OCTET STRING,
00068  *     url         Url
00069  * }
00070  */
00071 static const struct arm_uc_mmDerElement manifestResourceAlias[] =
00072 {
00073     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00074     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_MANDATORY),
00075 };
00076 /**
00077  * @brief Descriptor of an Alias container
00078  *
00079  */
00080 static const struct arm_uc_mmDerElement manifestResourceAliases[] =
00081 {
00082     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestResourceAlias)
00083 };
00084 
00085 /**
00086  * @brief Descriptor of the firmware format
00087  *
00088  * format      CHOICE {F
00089  *     enum    ENUMERATED {
00090  *         undefined(0), raw-binary(1), cbor(2), hex-location-length-data(3), elf(4)
00091  *     },
00092  *     objectId    OBJECT IDENTIFIER
00093  * },
00094  */
00095 static const struct arm_uc_mmDerElement manifestFwFmtChoice[] =
00096 {
00097     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_FMT_ENUM, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
00098     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_FMT_OID, ARM_UC_MM_ASN1_OID, DER_MANDATORY),
00099 };
00100 
00101 /**
00102  * @brief Descriptor of the certificate reference used for ECDH
00103  * @details References an ECC certificate, which is used to perform ECDH with the target device's private key. This will
00104  * allow derivation of a shared secret, which has been used to encrypt the symmetric encryption key.
00105  * NOTE: this is the same ASN.1 sequence as arm_uc_mmSignatureCertificateReference, but it is duplicated in the parser to reduce parsing time.
00106  *
00107  * CertificateReference ::= SEQUENCE {
00108  *     fingerprint  Bytes,
00109  *     url          Url
00110  * }
00111  *
00112  */
00113 static const struct arm_uc_mmDerElement manifestFwCryptIdCertRef[] =
00114 {
00115     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00116     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00117 };
00118 /**
00119  * @brief Descriptor of the Local Info ID choice
00120  * @details Describes either a locally held pre-shared key or a certificate.
00121  *
00122  * id CHOICE {
00123  *     key OCTET STRING,
00124  *     certificate CertificateReference
00125  * },
00126  */
00127 static const struct arm_uc_mmDerElement manifestFwCryptIdChoice[] =
00128 {
00129     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_LOCAL, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00130     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_REF, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestFwCryptIdCertRef),
00131 };
00132 /**
00133  * @brief Descriptor of the encryption key options
00134  * @details Encryption is currently not supported.
00135  * When supported, the encryption key will be delivered either as an encrypted blob in the manifest, or in a key table,
00136  * which is referenced in the Resource Reference below.
00137  *
00138  * key      CHOICE {
00139  *   keyTable  Url,
00140  *   cipherKey OCTET STRING
00141  * } OPTIONAL
00142  *
00143  */
00144 static const struct arm_uc_mmDerElement manifestFwCryptKeyChoice[] =
00145 {
00146     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF, ARM_UC_MM_ASN1_UTF8_STRING, DER_MANDATORY),
00147     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00148 };
00149 /**
00150  * @brief Descriptor of cryptographic information block
00151  * @details Contains the information necessary to manage the encryption of the payload.
00152  * encryptionInfo SEQUENCE {
00153  *     initVector OCTET STRING,
00154  *     id,
00155  *     key
00156  * } OPTIONAL,
00157  */
00158 static const struct arm_uc_mmDerElement manifestFwCryptInfo[] =
00159 {
00160     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_IV, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00161     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_MANDATORY, manifestFwCryptIdChoice),
00162     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_OPTIONAL, manifestFwCryptKeyChoice),
00163 };
00164 
00165 /**
00166  * @brief Descriptor of a firmware resource reference.
00167  * @details Provides a hash, URL, and size of a payload
00168  *
00169  * ResourceReference ::= SEQUENCE {
00170  *   hash        OCTET STRING,
00171  *   url     Url OPTIONAL,
00172  *   size    INTEGER
00173  * }
00174  */
00175 static const struct arm_uc_mmDerElement manifestFwRsrcRef[] =
00176 {
00177     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00178     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00179     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
00180 };
00181 
00182 /**
00183  * @brief Descriptor of a payload description block
00184  * @details Describes the payload, including:
00185  * * The payload format
00186  * * Any cryptographic information required to decrypt the payload
00187  * * The storage identifier for payload (where to store it on the target)
00188  * * The resource reference of the payload (where it is stored, etc)
00189  * * A free-text version field
00190  *
00191  * FirmwareDescription ::= SEQUENCE {
00192  *    format,
00193  *    encryptionInfo OPTIONAL,
00194  *    storageIdentifier UTF8String,
00195  *    reference    ResourceReference,
00196  *    version     UTF8String OPTIONAL
00197  * }
00198  */
00199 static const struct arm_uc_mmDerElement arm_uc_mmManifestFirmwareDescriptionElements[] =
00200 {
00201     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_FMT_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_MANDATORY, manifestFwFmtChoice),
00202     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_INFO, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, manifestFwCryptInfo),
00203     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_STRG_ID, ARM_UC_MM_ASN1_UTF8_STRING, DER_MANDATORY),
00204     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_RSRC_REF, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestFwRsrcRef),
00205     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_VER, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00206 };
00207 
00208 const struct arm_uc_mmDerElement arm_uc_mmManifestFirmwareDescription[] =
00209 {
00210     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FIRMWARE, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, arm_uc_mmManifestFirmwareDescriptionElements),
00211 };
00212 
00213 /**
00214  * @brief Descriptor of a manifest dependency reference
00215  * @details Provides a hash, URL, and size of a manifest dependency
00216  * ResourceReference ::= SEQUENCE {
00217  *     hash        OCTET STRING,
00218  *     url     Url OPTIONAL,
00219  *     size    INTEGER
00220  * }
00221  */
00222 static const struct arm_uc_mmDerElement arm_uc_mmManifestDependency[] =
00223 {
00224     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEP_REF_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00225     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEP_REF_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00226     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEP_REF_SIZE, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
00227 };
00228 /**
00229  * @brief Descriptor of a manifest dependency container
00230  * @details Contains manifest dependency references
00231  */
00232 const struct arm_uc_mmDerElement arm_uc_mmManifestDependencies[] =
00233 {
00234     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_DEP, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmManifestDependency)
00235 };
00236 
00237 /**
00238  * @brief Descriptor of the manifest sequence
00239  * @details Contains all the information necessary to describe a manifest.
00240  *
00241  * Manifest ::= SEQUENCE {
00242  *     manifestVersion     ENUMERATED {
00243  *       v1(1)
00244  *     },
00245  *     description UTF8String OPTIONAL,
00246  *     timestamp   INTEGER,
00247  *     vendorId    UUID,
00248  *     classId     UUID,
00249  *     deviceId    UUID,
00250  *     nonce       OCTET STRING,
00251  *     vendorInfo  OCTET STRING,
00252  *     applyPeriod OPTIONAL,
00253  *     applyImmediately    BOOLEAN,
00254  *     encryptionMode  CHOICE {
00255  *         enum    ENUMERATED {
00256  *             invalid(0),
00257  *             aes-128-ctr-ecc-secp256r1-sha256(1),
00258  *             none-ecc-secp256r1-sha256(2),
00259  *             none-none-sha256(3)
00260  *         },
00261  *         objectId    OBJECT IDENTIFIER
00262  *     },
00263  *     aliases         SEQUENCE OF ResourceAlias,
00264  *     dependencies    SEQUENCE OF ResourceReference,
00265  *     firmware        FirmwareDescription OPTIONAL
00266  */
00267 static const struct arm_uc_mmDerElement ManifestElements[] =
00268 {
00269     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VERSION, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
00270     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DESC, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00271     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_TIMESTAMP, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
00272     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VENDOR_UUID, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00273     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_CLASS_UUID, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00274     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEVICE_UUID, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00275     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_NONCE, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00276     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VENDOR_INFO, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00277     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_APPLY_PERIOD, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, ManifestApplyPeriod),
00278     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_APPLY_IMMEDIATELY, ARM_UC_MM_ASN1_BOOLEAN, DER_MANDATORY),
00279     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_ENCRYPTION_MODE_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_OPTIONAL, encryptionModeChoice),
00280     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_RESOURCE_ALIASES, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestResourceAliases),
00281     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_DEPS, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmManifestDependencies),
00282     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FIRMWARE, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, arm_uc_mmManifestFirmwareDescriptionElements),
00283 };
00284 
00285 /**
00286  * @brief Descriptor of the Resource Choice
00287  * @details The resource can be one of a limited number of options. Currently, the supported resource types are Manifest
00288  * and Firmware Image. The firmware image is simply an OCTET STRING, whereas the Manifest is an ASN.1 SEQUENCE (DER
00289  * encoded)
00290  *
00291  * resource CHOICE {
00292  *     manifest Manifest,
00293  *     firmware Firmware
00294  * }
00295  */
00296 static const struct arm_uc_mmDerElement ResourceChoiceElements[] =
00297 {
00298     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, ManifestElements),
00299     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_FW_IMAGE, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00300 };
00301 
00302 /**
00303  * @brief Descriptor of a Resource object.
00304  * @details A resource is composed of an optional reference URL, a resource type identifier, and a resource.
00305  *
00306  * Resource ::= SEQUENCE {
00307  *     url     Url OPTIONAL,
00308  *     resourceType        ENUMERATED {
00309  *         manifest(0), firmware(1)
00310  *     },
00311  *     resource
00312  * }
00313  */
00314 static const struct arm_uc_mmDerElement ResourceElements[] =
00315 {
00316     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_RESOURCE_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00317     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_RESOURCE_TYPE, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
00318     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_RESOURCE_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_MANDATORY, ResourceChoiceElements),
00319 };
00320 /**
00321 * @brief Descriptor of the certificate reference used for ECDSA signature verification
00322 * @details References an ECC certificate, which is used to perform ECDSA with the target device's public key. The
00323 * certificate used to sign the manifest is used to determine the permissions to be applied to the manifest.
00324 * NOTE: this is the same ASN.1 sequence as manifestFwCryptIdCertRef, but it is duplicated in the parser to reduce parsing time.
00325 *
00326 * CertificateReference ::= SEQUENCE {
00327 *     fingerprint  Bytes,
00328 *     url          Url
00329 * }
00330 
00331  */
00332 static const struct arm_uc_mmDerElement arm_uc_mmSignatureCertificateReference[] =
00333 {
00334     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_CERT_FINGERPRINT, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00335     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_CERT_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
00336 };
00337 /**
00338  * @brief Certificate Reference container
00339  */
00340 const struct arm_uc_mmDerElement arm_uc_mmSignatureCertificateReferences[] =
00341 {
00342     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_CERT, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatureCertificateReference),
00343 };
00344 
00345 const struct arm_uc_mmDerElement arm_uc_mmSignatureBlock[] =
00346 {
00347     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_SIGNATURE, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00348     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_CERTS, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatureCertificateReferences),
00349 };
00350 const struct arm_uc_mmDerElement arm_uc_mmSignatures[] =
00351 {
00352     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_SIGNATURE_BLOCK, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatureBlock),
00353 };
00354 /**
00355  * @brief Descriptor of a resource signature
00356  * @details Contains the signature of the resource object. To facilitate fast integrity checking, a hash is also
00357  * provided. The certificate references allow the target device to establish a chain of trust.
00358  *
00359  * ResourceSignature ::= SEQUENCE {
00360  *     certificates SEQUENCE OF CertificateReference,
00361  *     hash        OCTET STRING,
00362  *     signature   OCTET STRING
00363  * }
00364  */
00365 const struct arm_uc_mmDerElement arm_uc_mmResourceSignature[] =
00366 {
00367     ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
00368     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_SIGNATURES, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatures),
00369 };
00370 /**
00371  * @brief Descriptor of a signed resource.
00372  * @details The signed resource is a container for a resource and a signature.
00373  * SignedResource ::= SEQUENCE {
00374  *     resource  Resource,
00375  *     signature ResourceSignature
00376  * }
00377  */
00378 static const struct arm_uc_mmDerElement SignedResourceElements[] =
00379 {
00380     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_RESOURCE, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, ResourceElements),
00381     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmResourceSignature),
00382 };
00383 /**
00384  * @brief Container of a Signed Resource.
00385  */
00386 static const struct arm_uc_mmDerElement SignedResource =
00387     ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_ROOT, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, SignedResourceElements);
00388 
00389 #include "update-client-common/arm_uc_trace.h"
00390 
00391 enum arm_uc_mmDerParserLogLevels {
00392     DER_PARSER_LOG_LEVEL_NONE,
00393     DER_PARSER_LOG_LEVEL_DESCRIPTORS,
00394     DER_PARSER_LOG_LEVEL_TAGS,
00395     DER_PARSER_LOG_LEVEL_SIZES,
00396     DER_PARSER_LOG_LEVEL_VALUES,
00397     DER_PARSER_LOG_LEVEL_MAX
00398 };
00399 uint32_t arm_uc_mm_derRecurseDepth;
00400 
00401 #ifndef ARM_UC_DER_PARSER_TRACE_ENABLE
00402 #define ARM_UC_DER_PARSER_TRACE_ENABLE 0
00403 #endif
00404 
00405 #if ARM_UC_DER_PARSER_TRACE_ENABLE
00406 volatile uint32_t arm_uc_mm_der_gDebugLevel = DER_PARSER_LOG_LEVEL_MAX;
00407 
00408 #define DER_PARSER_LOG_INDENT(LOG_LEVEL)\
00409 do { \
00410     if((LOG_LEVEL) <= arm_uc_mm_der_gDebugLevel) \
00411     { \
00412         for (uint32_t i = 0; i < arm_uc_mm_derRecurseDepth; i++) \
00413         { \
00414             printf("  "); \
00415         } \
00416     } \
00417 } while(0)
00418 
00419 #define DER_PARSER_LOG(LOG_LEVEL,...)\
00420     do { \
00421         if((LOG_LEVEL) <= arm_uc_mm_der_gDebugLevel) \
00422         { \
00423             printf(__VA_ARGS__); \
00424         } \
00425     } while(0)
00426 #else
00427 #define DER_PARSER_LOG_INDENT(LOG_LEVEL)
00428 #define DER_PARSER_LOG(LOG_LEVEL,...)
00429 #endif
00430 
00431 /*
00432  * ASN.1 DER decoding routines
00433  */
00434 int ARM_UC_MM_ASN1_get_len( unsigned char **p,
00435                   const unsigned char *end,
00436                   size_t *len )
00437 {
00438     if( ( end - *p ) < 1 )
00439         return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00440 
00441     if( ( **p & 0x80 ) == 0 )
00442         *len = *(*p)++;
00443     else
00444     {
00445         switch( **p & 0x7F )
00446         {
00447         case 1:
00448             if( ( end - *p ) < 2 )
00449                 return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00450 
00451             *len = (*p)[1];
00452             (*p) += 2;
00453             break;
00454 
00455         case 2:
00456             if( ( end - *p ) < 3 )
00457                 return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00458 
00459             *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
00460             (*p) += 3;
00461             break;
00462 
00463         case 3:
00464             if( ( end - *p ) < 4 )
00465                 return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00466 
00467             *len = ( (size_t)(*p)[1] << 16 ) |
00468                    ( (size_t)(*p)[2] << 8  ) | (*p)[3];
00469             (*p) += 4;
00470             break;
00471 
00472         case 4:
00473             if( ( end - *p ) < 5 )
00474                 return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00475 
00476             *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
00477                    ( (size_t)(*p)[3] << 8  ) |           (*p)[4];
00478             (*p) += 5;
00479             break;
00480 
00481         default:
00482             return( ARM_UC_DP_ERR_ASN1_INVALID_LENGTH );
00483         }
00484     }
00485 
00486     if( *len > (size_t) ( end - *p ) )
00487         return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00488 
00489     return( 0 );
00490 }
00491 
00492 int ARM_UC_MM_ASN1_get_tag( unsigned char **p,
00493                   const unsigned char *end,
00494                   size_t *len, int tag )
00495 {
00496     if( ( end - *p ) < 1 )
00497         return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
00498 
00499     if( **p != tag )
00500         return( ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG );
00501 
00502     (*p)++;
00503 
00504     return( ARM_UC_MM_ASN1_get_len( p, end, len ) );
00505 }
00506 
00507 
00508 const char* ARM_UC_mmDERDescID2Str(uint32_t id)
00509 {
00510     switch (id) {
00511         #define ENUM_AUTO(name) case name: return #name;
00512         ARM_UC_MM_DER_ID_LIST
00513         #undef ENUM_AUTO
00514     default:
00515         return "Unknown DER ID";
00516     }
00517 }
00518 
00519 /**
00520  * @brief Internal state of the parser
00521  */
00522 struct ARM_UC_MM_DERParserState {
00523     uint32_t nValues;         //!< Number of values remaining to parse
00524     const int32_t* valueIDs; //!< Current element of the value identifier array
00525     arm_uc_buffer_t* buffers; //!< Current buffer of the value output array
00526 };
00527 /**
00528  * @brief Converts a buffer to an unsigned 32-bit integer
00529  * @details Assumes that the buffer is an unsigned, big-endian integer and returns it.
00530  * Limitations:
00531  * * Expects the buffer to be 4 bytes long or less
00532  * * Does not trap NULL buffers
00533  * * Does not trap NULL pointers
00534  * * Does not permit sign extension of negative values
00535  * @param[in] buf The buffer to convert to an integer
00536  * @return The integer value of the buffer
00537  */
00538 uint32_t ARM_UC_mmDerBuf2Uint(arm_uc_buffer_t* buf)
00539 {
00540     uint32_t rc = 0;
00541     unsigned i;
00542     for (i = 0; i < buf->size && i < sizeof(uint32_t); i++)
00543     {
00544         rc = (rc << 8) | buf->ptr[i];
00545     }
00546     return rc;
00547 }
00548 /**
00549  * @brief Converts a buffer to an unsigned 64-bit integer
00550  * @details Assumes that the buffer is an unsigned, big-endian integer and returns it.
00551  * Limitations:
00552  * * Expects the buffer to be 8 bytes long or less
00553  * * Does not trap NULL buffers
00554  * * Does not trap NULL pointers
00555  * * Does not permit sign extension of negative values
00556  * @param[in] buf The buffer to convert to an integer
00557  * @return The integer value of the buffer
00558  */
00559 uint64_t ARM_UC_mmDerBuf2Uint64(arm_uc_buffer_t* buf)
00560 {
00561     uint64_t rc = 0;
00562     unsigned i;
00563     for (i = 0; i < buf->size && i < sizeof(uint64_t); i++)
00564     {
00565         rc = (rc << 8) | buf->ptr[i];
00566     }
00567     return rc;
00568 }
00569 
00570 /**
00571  * @brief Extracts the next tag in the DER string
00572  * @details Validates the length of the string, then extracts the next value, interpreting it as a tag.
00573  * Limitations:
00574  * * Does not verify that any of the pointers are non-NULL
00575  * * Does not validate tag values
00576  * @param[in] p The current position in DER string
00577  * @param[in] end The last position in the DER string
00578  * @param[out] tag The extracted DER tag
00579  * @retval 1 if the end has been encountered
00580  * @retval 0 if the tag was successfully retrieved
00581  */
00582 int ARM_UC_mmDERPeekTag(uint8_t* p, uint8_t* end, int* tag)
00583 {
00584     if( ( end - p ) < 1 )
00585     {
00586         return( 1 );
00587     }
00588     *tag = *p;
00589     return 0;
00590 }
00591 
00592 /**
00593  * @brief Extracts one or more tagged values from DER encoded data
00594  * @details Recursively traverses the DER tree, searching for the identified values.
00595  * The parser parses the input data, identified by `*pos` according to the following rules:
00596  *
00597  * * If the current descriptor is a choice, `ARM_UC_mmDERGetValues` attempts to resolve the choice.
00598  *     * Obtain the actual tag
00599  *     * Loop through each child of the choice element and compare it to the tag
00600  *     * If no tag mathces, return `ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG`
00601  *     * Otherwise replace `desc` with the descriptor of the matching tag
00602  * * Get the tag for the current descriptor
00603  * * If the tag is not found
00604  *     * If it was optional, exit with success
00605  *     * Otherwise, exit with ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG
00606  * * If the descriptor ID matches the current extraction ID
00607  *     * Extract the value into the current buffer.
00608  *     * Advance the ID pointer, the buffer pointer, and decrement the value pointer.
00609  * * If the descriptor is a sequence with more than one child, recurse into it (single-child sequences are SEQUENCE OF)
00610  *     * For each child element,
00611  *         * If the end has been not reached or the child descriptor is mandatory
00612  *             * call `ARM_UC_mmDERGetValues` with the child descriptor.
00613  * * If the end does not match pos
00614  *     * fail with `ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH`
00615  * * Otherwise
00616  *     * Update the current position
00617  * * return success
00618  *
00619  * WARNING: ARM_UC_mmDERGetValues cannot resolve choices between two different sequences.
00620  *
00621  * NOTE: Choices are not currently returnable
00622  * NOTE: An optimization should be possible to reduce the parsing time by skipping elements whose descriptors do not
00623  *       contain the next requested element ID
00624  * NOTE: Length mismatch checking is not currently supported.
00625  *
00626  * To parse a SEQUENCE OF element, search for the SEQUENCE OF. Then, iterate through its elements with
00627  * `ARM_UC_mmDERGetSequenceElement`. With each element, call `ARM_UC_mmDERParseTree` with the descriptor for the
00628  * contents of the SEQUENCE OF.
00629  *
00630  * @param[in] desc Contains the current parsing descriptor
00631  * @param[in] pos Pointer to pointer that holds the current parsing location
00632  * @param[in] end Pointer to the end of the current element's container
00633  * @param[in,out] state Parser state. Contains the parser's
00634  * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
00635  * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
00636  * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
00637  * @retval 0                                Success!
00638  */
00639 int32_t ARM_UC_mmDERGetValues(const struct arm_uc_mmDerElement* desc, uint8_t** pos, uint8_t* end, struct ARM_UC_MM_DERParserState* state)
00640 {
00641     size_t len;
00642     int rc;
00643     uint8_t* ElementEnd;
00644     DER_PARSER_LOG_INDENT(DER_PARSER_LOG_LEVEL_DESCRIPTORS);
00645     DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "%s", ARM_UC_mmDERDescID2Str(desc->id));
00646 
00647     // TODO: return a choice result when a choice ID is in the list.
00648     // Resolve the a choice. Cannot distinguish choices between two sequences.
00649     if (desc->tag == ARM_UC_MM_ASN1_CHOICE)
00650     {
00651         int tag;
00652         unsigned i;
00653         DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "\n");
00654         // Get the tag of the next element and identify the descriptor that matches that tag.
00655         rc = ARM_UC_mmDERPeekTag(*pos, end, &tag);
00656         if (rc)
00657             return rc;
00658         rc = ( ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG );
00659         arm_uc_mm_derRecurseDepth++;
00660         for (i = 0; i < desc->nSubElements; i++)
00661         {
00662             if (tag == desc->subElements[i].tag)
00663             {
00664                 // desc = &desc->subElements[i];
00665                 // rc = 0;
00666                 rc = ARM_UC_mmDERGetValues(&desc->subElements[i], pos, end, state);
00667                 break;
00668             }
00669             else
00670             {
00671                 DER_PARSER_LOG_INDENT(DER_PARSER_LOG_LEVEL_DESCRIPTORS);
00672                 DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "%s (skipped)\n", ARM_UC_mmDERDescID2Str(desc->subElements[i].id));
00673             }
00674         }
00675         arm_uc_mm_derRecurseDepth--;
00676         // If the matching tag is not in one of the desctiptors, then a parse error has been encountered.
00677         // if (rc)
00678         return rc;
00679     }
00680     // Store the entry position for saving sequences
00681     uint8_t* seqpos = *pos;
00682     // Get the next tag & length, advancing the parse position to just after the tag/length pair.
00683     rc = ARM_UC_MM_ASN1_get_tag(pos, end, &len, desc->tag);
00684     // If an optional tag was expected, but not encountered, it is not an error unless it was requested by the user.
00685     if (rc == ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG && desc->optional && desc->id != (unsigned)(state->valueIDs[0]))
00686     {
00687         DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, " (skipped)\n");
00688         return 0;
00689     } // TODO evaluate length handling in ARM_UC_MM_ASN1_get_tag
00690     // If an error was encountered, abort.
00691     if (rc)
00692     {
00693         DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, " (error %d)\n", rc);
00694         return rc;
00695     }
00696     // If the encountered tag is one of the requested IDs, record its location and size, then move on to the next value
00697     if (desc->id == (unsigned)(state->valueIDs[0]))
00698     {
00699         // If the element is a sequence, store the whole element, not just the content.
00700         if (desc->tag == (ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE) && desc->nSubElements != 1)
00701         {
00702             state->buffers[0].ptr = seqpos;
00703             state->buffers[0].size = len + (*pos - seqpos);
00704             state->buffers[0].size_max = len + (*pos - seqpos);
00705         }
00706         else
00707         {
00708             state->buffers[0].ptr = *pos;
00709             state->buffers[0].size = len;
00710             state->buffers[0].size_max = len;
00711         }
00712         state->nValues--;
00713         state->valueIDs++;
00714         state->buffers++;
00715         DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, " (stored)\n");
00716     }
00717     else
00718     {
00719         DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "\n");
00720     }
00721     DER_PARSER_LOG_INDENT(DER_PARSER_LOG_LEVEL_TAGS);
00722     DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_TAGS, "%02X", desc->tag);
00723     DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_SIZES, " %X", len);
00724     if (desc->tag != (ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE))
00725     {
00726         DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_VALUES, " ");
00727         for (uint32_t i = 0; i < len; i++)
00728         {
00729             if (desc->tag == ARM_UC_MM_ASN1_UTF8_STRING)
00730             {
00731                 DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_VALUES, "%c", (char)(*pos)[i]);
00732             }
00733             else
00734             {
00735                 DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_VALUES, "%X", (*pos)[i]);
00736             }
00737         }
00738     }
00739     DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_TAGS, "\n");
00740 
00741     // TODO: At this point, it should be possible to exit parsing of this element early if no requested ID is owned by
00742     // this element or one of its children.
00743 
00744     // Update the end of the current element to pos+len
00745     ElementEnd = *pos + len;
00746     // If the element is a sequence, parse the sequence.
00747     if (desc->tag == (ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE))
00748     {
00749         /* Sequences with only a single element are treated as a SEQUENCE OF, which has special semantics. In order to
00750          * extract the contents of a SEQUENCE OF, the caller must request the SEQUENCE OF element ID, then use
00751          * ARM_UC_mmDERGetSequenceElement to extract the contents of the sequence, passing each one to
00752          * ARM_UC_mmDERParseTree in order to extract any */
00753         if (desc->nSubElements != 1) // SEQUENCE
00754         {
00755             int i;
00756             end = *pos + len;
00757             arm_uc_mm_derRecurseDepth++;
00758             for ( i = 0; rc == 0 && state->nValues != 0 && i < desc->nSubElements; i++ )
00759             {
00760                 // Escape if the end has been reached and the parsing elements are optional
00761                 if (!(*pos >= end && desc->subElements[i].optional)) {
00762                     // Parse a sub-tree
00763                     rc = ARM_UC_mmDERGetValues(&desc->subElements[i], pos, end, state);
00764                 }
00765             }
00766             arm_uc_mm_derRecurseDepth--;
00767         }
00768     }
00769 
00770     if (*pos > ElementEnd) // TODO: Add length mismatch check
00771     {
00772         // Fail if there is a length mismatch
00773         return ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH;
00774     }
00775     else
00776     {
00777         // Update the current parsing position
00778         *pos = ElementEnd;
00779     }
00780     return rc;
00781 }
00782 
00783 /**
00784  * @brief Extracts elements from an ASN.1 SEQUENCE OF by index
00785  * @details Parses a SEQUENCE OF element, skipping elements until it finds the requested element.
00786  * When the last element has been parsed, a further call to `ARM_UC_mmDERGetSequenceElement` will cause element to be
00787  * populated with a NULL buffer pointer and 0 length, but `ARM_UC_mmDERGetSequenceElement` will still return success.
00788  *
00789  * @param[in]  buffer  The data to parse
00790  * @param[in]  index   The element index to extract
00791  * @param[out] element The buffer to populate with the extracted element
00792  *
00793  * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
00794  * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
00795  * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
00796  * @retval 0                                Success!
00797  */
00798 int32_t ARM_UC_mmDERGetSequenceElement(arm_uc_buffer_t* buffer, uint32_t index, arm_uc_buffer_t* element)
00799 {
00800     uint8_t* pos      = buffer->ptr;
00801     uint8_t* end      = pos + buffer->size;
00802     int rc            = 0;
00803     size_t len        = 0;
00804     element->ptr      = NULL;
00805     element->size     = 0;
00806     element->size_max = 0;
00807     for(; !rc; index--)
00808     {
00809         int tag;
00810         rc = ARM_UC_mmDERPeekTag(pos, end, &tag);
00811         if (rc)
00812         {
00813             // Peek-tag can only fail if pos >= end, so there was no element
00814             // This is not an error, since the parser may not know how many elements are in the sequence.
00815             return 0;
00816         }
00817         if (!index)
00818         {
00819             element->ptr = pos;
00820         }
00821         rc = ARM_UC_MM_ASN1_get_tag(&pos, end, &len, tag);
00822         if (!index && !rc)
00823         {
00824             element->size     = len + pos - element->ptr;
00825             element->size_max = element->size;
00826             break;
00827         }
00828         if (rc)
00829         {
00830             element->ptr = NULL;
00831             break;
00832         }
00833         pos += len;
00834     }
00835     return rc;
00836 }
00837 
00838 /**
00839  * @brief Parses a tree of DER data by calling `ARM_UC_mmDERGetValues`
00840  * @details Populates a parser state with the IDs to be extracted, the number of values and the buffers to extract into
00841  * @param[in]  desc     Contains the current parsing descriptor
00842  * @param[in]  buffer   The data to parse
00843  * @param[in]  nValues  The number of values to search for
00844  * @param[in]  valueIDs Array of value identifiers
00845  * @param[out] buffers  Array of buffers to populate with the elements matching valueIDs
00846  * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
00847  * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
00848  * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
00849  * @retval 0                                Success!
00850  * @retval >0                               Number of remaining elements
00851  */
00852 int32_t ARM_UC_mmDERParseTree(const struct arm_uc_mmDerElement* desc, arm_uc_buffer_t* buffer, uint32_t nValues, const int32_t* valueIDs, arm_uc_buffer_t* buffers)
00853 {
00854     uint8_t *pos = buffer->ptr;
00855     uint8_t *end = pos + buffer->size;
00856     struct ARM_UC_MM_DERParserState state = {
00857         nValues, valueIDs, buffers
00858     };
00859     arm_uc_mm_derRecurseDepth = 0;
00860     int32_t rc = ARM_UC_mmDERGetValues(desc, &pos, end, &state);
00861     // printf("Failed at: index %lu: %lu with return code: %ld\n", nValues-state.nValues, *state.valueIDs, rc);
00862     if (rc == 0 && state.nValues != 0)
00863     {
00864         return state.nValues;
00865     }
00866     return rc;
00867 }
00868 /**
00869  * @brief Parses a tree of DER data by calling `ARM_UC_mmDERGetValues`
00870  * @details Populates a parser state with the IDs to be extracted, the number of values and the buffers to extract into
00871  * Calls `ARM_UC_mmDERParseTree` with `SignedResource`
00872  * @param[in]  buffer   The data to parse
00873  * @param[in]  nValues  The number of values to search for
00874  * @param[in]  valueIDs Array of value identifiers
00875  * @param[out] buffers  Array of buffers to populate with the elements matching valueIDs
00876  * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
00877  * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
00878  * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
00879  * @retval 0                                Success!
00880  * @retval >0                               Number of remaining elements
00881  */
00882 int32_t ARM_UC_mmDERGetSignedResourceValues(arm_uc_buffer_t* buffer, uint32_t nValues, const int32_t* valueIDs, arm_uc_buffer_t* buffers)
00883 {
00884     return ARM_UC_mmDERParseTree(&SignedResource, buffer, nValues, valueIDs, buffers);
00885 }