leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_device_identity_kcm.c Source File

arm_uc_device_identity_kcm.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 "pal4life-device-identity/pal_device_identity.h"
00020 #include "update-client-common/arm_uc_config.h"
00021 #include <stdint.h>
00022 
00023 #if defined(ARM_UC_FEATURE_IDENTITY_KCM) && (ARM_UC_FEATURE_IDENTITY_KCM == 1)
00024 
00025 #include "key-config-manager/key_config_manager.h"
00026 
00027 #define SIZE_OF_GUID (sizeof(arm_uc_guid_t))
00028 // Hex encoded GUIDs with up to 4 hyphens.
00029 #define SIZE_OF_TEXT_GUID ((SIZE_OF_GUID) * 2 + 4)
00030 
00031 /* these defines are copied from:
00032    mbed-cloud-client/source/include/CloudClientStorage.h
00033 */
00034 #define KEY_DEVICE_MANUFACTURER_DEPRECATED      "mbed.Manufacturer"
00035 #define KEY_DEVICE_MODELNUMBER_DEPRECATED       "mbed.ModelNumber"
00036 #define KEY_ENDPOINT_NAME                       "mbed.EndpointName"
00037 #define KEY_VENDOR_ID                           "mbed.VendorId"
00038 #define KEY_CLASS_ID                            "mbed.ClassId"
00039 
00040 static arm_uc_error_t pal_kcm_internal_set_guid(const arm_uc_guid_t *guid,
00041                                                 const char *key,
00042                                                 size_t key_length)
00043 {
00044     arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
00045 
00046     if (guid && key) {
00047         kcm_status_e  kcm_status = kcm_item_store((const uint8_t *) key,
00048                                                  key_length,
00049                                                  KCM_CONFIG_ITEM,
00050                                                  true,
00051                                                  (const uint8_t *) guid,
00052                                                  SIZE_OF_GUID,
00053                                                  NULL);
00054 
00055         if (kcm_status == KCM_STATUS_SUCCESS) {
00056             result.code = ERR_NONE;
00057         }
00058     }
00059 
00060     return result;
00061 }
00062 
00063 static arm_uc_error_t pal_kcm_internal_get_guid(arm_uc_guid_t *guid,
00064                                                 const char *key,
00065                                                 size_t key_length)
00066 {
00067     arm_uc_error_t result = (arm_uc_error_t){ARM_UC_DI_ERR_INVALID_PARAMETER};
00068     if (guid && key) {
00069         uint8_t buffer[SIZE_OF_GUID] = { 0 };
00070         size_t value_length = 0;
00071         memset(guid, 0, SIZE_OF_GUID);
00072 
00073         kcm_status_e  kcm_status = kcm_item_get_data((const uint8_t *) key,
00074                                                     key_length,
00075                                                     KCM_CONFIG_ITEM,
00076                                                     buffer,
00077                                                     SIZE_OF_GUID,
00078                                                     &value_length);
00079         if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00080             result.code = ARM_UC_DI_ERR_NOT_FOUND;
00081         }
00082 
00083         if (kcm_status == KCM_STATUS_SUCCESS) {
00084             result.code = ERR_NONE;
00085             memcpy(guid, buffer, SIZE_OF_GUID);
00086         }
00087     }
00088 
00089     return result;
00090 }
00091 
00092 static bool pal_kcm_internal_compare(const arm_uc_guid_t *guid,
00093                                      const arm_uc_buffer_t *buffer)
00094 {
00095     // count how many bytes match
00096     uint8_t index = 0;
00097 
00098     if (guid && buffer) {
00099         for (; (index < sizeof(arm_uc_guid_t)) && (index < buffer->size); index++) {
00100             // printf("%02X %02X\r\n", ((uint8_t*) guid)[index], buffer->ptr[index]);
00101 
00102             if (((uint8_t *) guid)[index] != buffer->ptr[index]) {
00103                 break;
00104             }
00105         }
00106     }
00107 
00108     // return true if all bytes matched
00109     return (index == sizeof(arm_uc_guid_t));
00110 }
00111 
00112 /**
00113  * @brief Function for setting the vendor GUID.
00114  * @details The GUID is copied.
00115  * @param guid Pointer to a arm_uc_guid_t GUID.
00116  * @param copy Boolean value indicating whether the value should be copied or
00117  *             referenced.
00118  * @return Error code.
00119  */
00120 arm_uc_error_t pal_kcm_setVendorGuid(const arm_uc_guid_t *guid)
00121 {
00122     return pal_kcm_internal_set_guid(guid,
00123                                      KEY_VENDOR_ID,
00124                                      sizeof(KEY_VENDOR_ID) - 1);
00125 }
00126 
00127 /**
00128  * @brief Function for getting a pointer to the vendor GUID.
00129  * @param guid Pointer to a arm_uc_guid_t pointer.
00130  * @return Error code.
00131  */
00132 arm_uc_error_t pal_kcm_getVendorGuid(arm_uc_guid_t *guid)
00133 {
00134     arm_uc_error_t err = pal_kcm_internal_get_guid(guid,
00135                                                    KEY_VENDOR_ID,
00136                                                    sizeof(KEY_VENDOR_ID) - 1);
00137     if (err.code == ARM_UC_DI_ERR_NOT_FOUND) {
00138         err = pal_kcm_internal_get_guid(guid,
00139                                         KEY_DEVICE_MANUFACTURER_DEPRECATED,
00140                                         sizeof(KEY_DEVICE_MANUFACTURER_DEPRECATED) - 1);
00141     }
00142     return err;
00143 }
00144 
00145 /**
00146  * @brief Function for setting the device class GUID.
00147  * @details The GUID is copied.
00148  * @param guid Pointer to a arm_uc_guid_t GUID.
00149  * @param copy Boolean value indicating whether the value should be copied or
00150  *             referenced.
00151  * @return Error code.
00152  */
00153 arm_uc_error_t pal_kcm_setClassGuid(const arm_uc_guid_t *guid)
00154 {
00155     return pal_kcm_internal_set_guid(guid,
00156                                      KEY_CLASS_ID,
00157                                      sizeof(KEY_CLASS_ID) - 1);
00158 }
00159 
00160 /**
00161  * @brief Function for getting a pointer to the device class GUID.
00162  * @param guid Pointer to a arm_uc_guid_t pointer.
00163  * @return Error code.
00164  */
00165 arm_uc_error_t pal_kcm_getClassGuid(arm_uc_guid_t *guid)
00166 {
00167     arm_uc_error_t err = pal_kcm_internal_get_guid(guid,
00168                                                    KEY_CLASS_ID,
00169                                                    sizeof(KEY_CLASS_ID) - 1);
00170     if (err.code == ARM_UC_DI_ERR_NOT_FOUND) {
00171         err = pal_kcm_internal_get_guid(guid,
00172                                         KEY_DEVICE_MODELNUMBER_DEPRECATED,
00173                                         sizeof(KEY_DEVICE_MODELNUMBER_DEPRECATED) - 1);
00174     }
00175     return err;
00176 }
00177 
00178 /**
00179  * @brief Function for setting the device GUID.
00180  * @details The GUID is copied.
00181  * @param guid Pointer to a arm_uc_guid_t GUID.
00182  * @param copy Boolean value indicating whether the value should be copied or
00183  *             referenced.
00184  * @return Error code.
00185  */
00186 arm_uc_error_t pal_kcm_setDeviceGuid(const arm_uc_guid_t *guid)
00187 {
00188     return pal_kcm_internal_set_guid(guid,
00189                                      KEY_ENDPOINT_NAME,
00190                                      sizeof(KEY_ENDPOINT_NAME) - 1);
00191 }
00192 
00193 /**
00194  * @brief Function for getting a pointer to the device GUID.
00195  * @param guid Pointer to a arm_uc_guid_t pointer.
00196  * @return Error code.
00197  */
00198 arm_uc_error_t pal_kcm_getDeviceGuid(arm_uc_guid_t *guid)
00199 {
00200     return pal_kcm_internal_get_guid(guid,
00201                                      KEY_ENDPOINT_NAME,
00202                                      sizeof(KEY_ENDPOINT_NAME) - 1);
00203 }
00204 
00205 
00206 /**
00207  * @brief Check whether the three GUIDs provided are valid on the device.
00208  * @details
00209  * @param vendor_buffer Buffer pointer to the Vendor GUID.
00210  * @param class_buffer  Buffer pointer to the device class GUID.
00211  * @param device_buffer Buffer pointer to the device GUID.
00212  * @param isValid     Pointer to the boolean return value.
00213  * @return Error code.
00214  */
00215 arm_uc_error_t pal_kcm_deviceIdentityCheck(const arm_uc_buffer_t *vendor_buffer,
00216                                            const arm_uc_buffer_t *class_buffer,
00217                                            const arm_uc_buffer_t *device_buffer)
00218 {
00219     arm_uc_error_t result = { .code = MFST_ERR_NULL_PTR };
00220 
00221     uint8_t parameters_set = 0;
00222     uint8_t parameters_ok = 0;
00223 
00224     /* check device - device is optional */
00225     if (device_buffer &&
00226             device_buffer->ptr &&
00227             (device_buffer->size > 0)) {
00228         parameters_set++;
00229 
00230         arm_uc_guid_t guid = { 0 };
00231 
00232         arm_uc_error_t retval = pal_kcm_getDeviceGuid(&guid);
00233 
00234         if (retval.code == ERR_NONE) {
00235             bool is_same = pal_kcm_internal_compare(&guid, device_buffer);
00236 
00237             if (is_same) {
00238                 parameters_ok++;
00239             } else {
00240                 result.code = MFST_ERR_GUID_DEVICE;
00241             }
00242         }
00243     }
00244 
00245     /* check class - class is optional */
00246     if (class_buffer &&
00247             class_buffer->ptr &&
00248             (class_buffer->size > 0)) {
00249         parameters_set++;
00250 
00251         arm_uc_guid_t guid = { 0 };
00252 
00253         arm_uc_error_t retval = pal_kcm_getClassGuid(&guid);
00254 
00255         if (retval.code == ERR_NONE) {
00256             bool is_same = pal_kcm_internal_compare(&guid, class_buffer);
00257 
00258             if (is_same) {
00259                 parameters_ok++;
00260             } else {
00261                 result.code = MFST_ERR_GUID_DEVCLASS;
00262             }
00263         }
00264     }
00265 
00266     /* check vendor - vendor is mandatory and has mask 0x10. */
00267     if (vendor_buffer &&
00268             vendor_buffer->ptr &&
00269             (vendor_buffer->size > 0)) {
00270         parameters_set += 0x10;
00271 
00272         arm_uc_guid_t guid = { 0 };
00273 
00274         arm_uc_error_t retval = pal_kcm_getVendorGuid(&guid);
00275 
00276         if (retval.code == ERR_NONE) {
00277             bool is_same = pal_kcm_internal_compare(&guid, vendor_buffer);
00278 
00279             if (is_same) {
00280                 parameters_ok += 0x10;
00281             } else {
00282                 result.code = MFST_ERR_GUID_VENDOR;
00283             }
00284         }
00285     }
00286 
00287     /* Device ID checks out when:
00288         - vendor match and neither class nor device is passed
00289         - vendor and class match and no device is passed
00290         - vendor and device match and no class is passed
00291         - vendor and class and device match
00292     */
00293     if ((parameters_set >= 0x10) && (parameters_set == parameters_ok)) {
00294         result.code = ERR_NONE;
00295     }
00296 
00297     return result;
00298 }
00299 
00300 const ARM_PAL_DEVICE_IDENTITY arm_uc_device_identity_kcm = {
00301     .SetVendorGuid          = pal_kcm_setVendorGuid,
00302     .GetVendorGuid          = pal_kcm_getVendorGuid,
00303     .SetClassGuid           = pal_kcm_setClassGuid,
00304     .GetClassGuid           = pal_kcm_getClassGuid,
00305     .SetDeviceGuid          = pal_kcm_setDeviceGuid,
00306     .GetDeviceGuid          = pal_kcm_getDeviceGuid,
00307     .DeviceIdentityCheck    = pal_kcm_deviceIdentityCheck
00308 };
00309 
00310 #endif // ARM_UC_FEATURE_IDENTITY_KCM