Simple interface for Mbed Cloud Client

Dependents:  

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