Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_metadata_header_v2.c Source File

arm_uc_metadata_header_v2.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 "update-client-metadata-header/arm_uc_metadata_header_v2.h"
00020 #include "update-client-metadata-header/arm_uc_buffer_utilities.h"
00021 #include <string.h>
00022 
00023 extern arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t *key, arm_uc_buffer_t *input, arm_uc_buffer_t *output);
00024 
00025 arm_uc_error_t ARM_UC_getDeviceKey256Bit(arm_uc_buffer_t *output)
00026 {
00027     arm_uc_error_t result = (arm_uc_error_t) { ARM_UC_CU_ERR_INVALID_PARAMETER };
00028 
00029     if (output->size_max >= ARM_UC_DEVICE_KEY_SIZE) {
00030         int8_t rv = mbed_cloud_client_get_rot_128bit(output->ptr, output->size_max);
00031         if (rv == 0) {
00032             arm_uc_buffer_t input = {
00033                 .size_max = ARM_UC_DEVICE_HMAC_KEY_SIZE,
00034                 .size = ARM_UC_DEVICE_HMAC_KEY_SIZE,
00035                 .ptr = (uint8_t *) &ARM_UC_DEVICE_HMAC_KEY
00036             };
00037             output->size = ARM_UC_ROT_SIZE;
00038 #if defined(PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC) && \
00039     (PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC == 1)
00040             result = ARM_UC_cryptoHMACSHA256(&input, output, output);
00041 #else
00042             result = ARM_UC_cryptoHMACSHA256(output, &input, output);
00043 #endif
00044         }
00045     }
00046 
00047     if (result.code != ERR_NONE) {
00048         /* clear buffer on failure so we don't leak the rot */
00049         memset(output->ptr, 0, output->size_max);
00050     }
00051 
00052     return result;
00053 }
00054 
00055 arm_uc_error_t arm_uc_parse_internal_header_v2(const uint8_t *input,
00056                                                arm_uc_firmware_details_t *details)
00057 {
00058     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00059 
00060     if (input && details) {
00061         /* calculate CRC */
00062         uint32_t calculatedChecksum = arm_uc_crc32(input, ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2);
00063 
00064         /* read out CRC */
00065         uint32_t temp32 = arm_uc_parse_uint32(&input[ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2]);
00066 
00067         if (temp32 == calculatedChecksum) {
00068             /* parse content */
00069             details->version = arm_uc_parse_uint64(&input[ARM_UC_INTERNAL_FIRMWARE_VERSION_OFFSET_V2]);
00070             details->size = arm_uc_parse_uint64(&input[ARM_UC_INTERNAL_FIRMWARE_SIZE_OFFSET_V2]);
00071 
00072             memcpy(details->hash,
00073                    &input[ARM_UC_INTERNAL_FIRMWARE_HASH_OFFSET_V2],
00074                    ARM_UC_SHA256_SIZE);
00075 
00076             memcpy(details->campaign,
00077                    &input[ARM_UC_INTERNAL_CAMPAIGN_OFFSET_V2],
00078                    ARM_UC_GUID_SIZE);
00079 
00080             /* set result */
00081             result.code = ERR_NONE;
00082         }
00083     }
00084 
00085     return result;
00086 }
00087 
00088 arm_uc_error_t arm_uc_create_internal_header_v2(const arm_uc_firmware_details_t *input,
00089                                                 arm_uc_buffer_t *output)
00090 {
00091     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00092 
00093     if (input &&
00094             output &&
00095             (output->size_max >= ARM_UC_INTERNAL_HEADER_SIZE_V2)) {
00096         /* zero buffer */
00097         memset(output->ptr, 0, ARM_UC_INTERNAL_HEADER_SIZE_V2);
00098 
00099         /* MSB encode header magic and version */
00100         arm_uc_write_uint32(&output->ptr[0],
00101                             ARM_UC_INTERNAL_HEADER_MAGIC_V2);
00102         arm_uc_write_uint32(&output->ptr[4],
00103                             ARM_UC_INTERNAL_HEADER_VERSION_V2);
00104 
00105         /* MSB encode firmware version */
00106         arm_uc_write_uint64(&output->ptr[ARM_UC_INTERNAL_FIRMWARE_VERSION_OFFSET_V2],
00107                             input->version);
00108 
00109         /* MSB encode firmware size to header */
00110         arm_uc_write_uint64(&output->ptr[ARM_UC_INTERNAL_FIRMWARE_SIZE_OFFSET_V2],
00111                             input->size);
00112 
00113         /* raw copy firmware hash to header */
00114         memcpy(&output->ptr[ARM_UC_INTERNAL_FIRMWARE_HASH_OFFSET_V2],
00115                input->hash,
00116                ARM_UC_SHA256_SIZE);
00117 
00118         /* raw copy campaign ID to header */
00119         memcpy(&output->ptr[ARM_UC_INTERNAL_CAMPAIGN_OFFSET_V2],
00120                input->campaign,
00121                ARM_UC_GUID_SIZE);
00122 
00123         /* calculate CRC */
00124         uint32_t checksum = arm_uc_crc32(output->ptr,
00125                                          ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2);
00126 
00127         /* MSB encode checksum to header */
00128         arm_uc_write_uint32(&output->ptr[ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2],
00129                             checksum);
00130 
00131         /* set output size */
00132         output->size = ARM_UC_INTERNAL_HEADER_SIZE_V2;
00133 
00134         /* set error code */
00135         result.code = ERR_NONE;
00136     }
00137 
00138     return result;
00139 }
00140 
00141 arm_uc_error_t arm_uc_parse_external_header_v2(const uint8_t *input,
00142                                                arm_uc_firmware_details_t *details)
00143 {
00144     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00145 
00146     if (input && details) {
00147 
00148         /* read 128 bit root-of-trust */
00149         uint8_t key_buf[ARM_UC_DEVICE_KEY_SIZE] = { 0 };
00150         arm_uc_buffer_t key = {
00151             .size_max = ARM_UC_DEVICE_KEY_SIZE,
00152             .size = 0,
00153             .ptr = key_buf
00154         };
00155         arm_uc_error_t status = ARM_UC_getDeviceKey256Bit(&key);
00156 
00157         if (status.error == ERR_NONE) {
00158             arm_uc_buffer_t input_buf = {
00159                 .size_max = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
00160                 .size = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
00161                 .ptr = (uint8_t *) input
00162             };
00163             arm_uc_hash_t hmac = { 0 };
00164             arm_uc_buffer_t output_buf = {
00165                 .size_max = sizeof(arm_uc_hash_t),
00166                 .size = sizeof(arm_uc_hash_t),
00167                 .ptr = (uint8_t *) &hmac
00168             };
00169 
00170             /* calculate header HMAC */
00171             status = ARM_UC_cryptoHMACSHA256(&key, &input_buf, &output_buf);
00172 
00173             if (status.error == ERR_NONE) {
00174                 input_buf.size_max = sizeof(arm_uc_hash_t);
00175                 input_buf.size = sizeof(arm_uc_hash_t);
00176                 input_buf.ptr = (uint8_t *) &input[ARM_UC_EXTERNAL_HMAC_OFFSET_V2];
00177 
00178                 int diff = ARM_UC_BinCompareCT(&input_buf, &output_buf);
00179 
00180                 if (diff == 0) {
00181                     details->version = arm_uc_parse_uint64(&input[ARM_UC_EXTERNAL_FIRMWARE_VERSION_OFFSET_V2]);
00182                     details->size = arm_uc_parse_uint64(&input[ARM_UC_EXTERNAL_FIRMWARE_SIZE_OFFSET_V2]);
00183 
00184                     memcpy(details->hash,
00185                            &input[ARM_UC_EXTERNAL_FIRMWARE_HASH_OFFSET_V2],
00186                            ARM_UC_SHA256_SIZE);
00187 
00188                     memcpy(details->campaign,
00189                            &input[ARM_UC_EXTERNAL_CAMPAIGN_OFFSET_V2],
00190                            ARM_UC_GUID_SIZE);
00191 
00192                     details->signatureSize = 0;
00193 
00194                     result.code = ERR_NONE;
00195                 }
00196             }
00197         }
00198     }
00199 
00200     return result;
00201 }
00202 
00203 arm_uc_error_t arm_uc_create_external_header_v2(const arm_uc_firmware_details_t *input,
00204                                                 arm_uc_buffer_t *output)
00205 {
00206     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00207 
00208     if (input &&
00209             output &&
00210             (output->size_max >= ARM_UC_EXTERNAL_HEADER_SIZE_V2)) {
00211         /* zero buffer and reset size*/
00212         memset(output->ptr, 0, ARM_UC_EXTERNAL_HEADER_SIZE_V2);
00213         output->size = 0;
00214 
00215         /* MSB encode header magic and version */
00216         arm_uc_write_uint32(&output->ptr[0],
00217                             ARM_UC_EXTERNAL_HEADER_MAGIC_V2);
00218         arm_uc_write_uint32(&output->ptr[4],
00219                             ARM_UC_EXTERNAL_HEADER_VERSION_V2);
00220 
00221         /* MSB encode firmware version */
00222         arm_uc_write_uint64(&output->ptr[ARM_UC_EXTERNAL_FIRMWARE_VERSION_OFFSET_V2],
00223                             input->version);
00224 
00225         /* MSB encode firmware size to header */
00226         arm_uc_write_uint64(&output->ptr[ARM_UC_EXTERNAL_FIRMWARE_SIZE_OFFSET_V2],
00227                             input->size);
00228 
00229         /* raw copy firmware hash to header */
00230         memcpy(&output->ptr[ARM_UC_EXTERNAL_FIRMWARE_HASH_OFFSET_V2],
00231                input->hash,
00232                ARM_UC_SHA256_SIZE);
00233 
00234         /* MSB encode payload size to header */
00235         arm_uc_write_uint64(&output->ptr[ARM_UC_EXTERNAL_PAYLOAD_SIZE_OFFSET_V2],
00236                             input->size);
00237 
00238         /* raw copy payload hash to header */
00239         memcpy(&output->ptr[ARM_UC_EXTERNAL_PAYLOAD_HASH_OFFSET_V2],
00240                input->hash,
00241                ARM_UC_SHA256_SIZE);
00242 
00243         /* raw copy campaign ID to header */
00244         memcpy(&output->ptr[ARM_UC_EXTERNAL_CAMPAIGN_OFFSET_V2],
00245                input->campaign,
00246                ARM_UC_GUID_SIZE);
00247 
00248         /* read 256 bit device key */
00249         uint8_t key_buf[ARM_UC_DEVICE_KEY_SIZE] = { 0 };
00250         arm_uc_buffer_t key = {
00251             .size_max = ARM_UC_DEVICE_KEY_SIZE,
00252             .size = 0,
00253             .ptr = key_buf
00254         };
00255 
00256         arm_uc_error_t status = ARM_UC_getDeviceKey256Bit(&key);
00257 
00258         if (status.error == ERR_NONE) {
00259             arm_uc_buffer_t input_buf = {
00260                 .size_max = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
00261                 .size = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
00262                 .ptr = output->ptr
00263             };
00264             arm_uc_buffer_t output_buf = {
00265                 .size_max = sizeof(arm_uc_hash_t),
00266                 .size = sizeof(arm_uc_hash_t),
00267                 .ptr = &output->ptr[ARM_UC_EXTERNAL_HMAC_OFFSET_V2]
00268             };
00269 
00270             /* calculate header HMAC */
00271             result = ARM_UC_cryptoHMACSHA256(&key, &input_buf, &output_buf);
00272             if (result.error == ERR_NONE) {
00273                 /* set output size */
00274                 output->size = ARM_UC_EXTERNAL_HEADER_SIZE_V2;
00275             }
00276         }
00277     }
00278 
00279     return result;
00280 }