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