Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
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 uint32_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 != 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 == 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 }
Generated on Tue Jul 12 2022 19:01:32 by 1.7.2