Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fcc_bundle_common_utils.c Source File

fcc_bundle_common_utils.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //  
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //  
00008 //     http://www.apache.org/licenses/LICENSE-2.0
00009 //  
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 // ----------------------------------------------------------------------------
00016 
00017 #include "fcc_bundle_handler.h"
00018 #include "cn-cbor.h"
00019 #include "pv_error_handling.h"
00020 #include "fcc_bundle_utils.h"
00021 #include "fcc_malloc.h"
00022 #include "general_utils.h"
00023 #include "fcc_utils.h"
00024 #include "factory_configurator_client.h"
00025 
00026 #define  FCC_MAX_SIZE_OF_STRING 512
00027 
00028 /** Gets name from cbor struct.
00029 *
00030 * @param text_cb[in]          The cbor text structure
00031 * @param name_out[out]        The out buffer for string data
00032 * @param name_len_out[out]    The actual size of output buffer
00033 *
00034 * @return
00035 *     true for success, false otherwise.
00036 */
00037 static bool get_data_name(const cn_cbor *text_cb, uint8_t **name_out, size_t *name_len_out)
00038 {
00039     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00040     SA_PV_ERR_RECOVERABLE_RETURN_IF((text_cb == NULL), false, "Cbor pointer is NULL");
00041     SA_PV_ERR_RECOVERABLE_RETURN_IF((name_out == NULL), false, "Invalid pointer for name");
00042     SA_PV_ERR_RECOVERABLE_RETURN_IF((name_len_out == NULL), false, "Invalid pointer for name_len");
00043 
00044     *name_out = (uint8_t*)fcc_malloc((size_t)(text_cb->length));
00045     SA_PV_ERR_RECOVERABLE_RETURN_IF((*name_out == NULL), false, "Failed to allocate buffer for name");
00046 
00047     memcpy(*name_out, text_cb->v.bytes, (size_t)text_cb->length);
00048     *name_len_out = (size_t)text_cb->length;
00049     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00050 
00051     return true;
00052 }
00053 
00054 /** Gets data format from cbor struct
00055 *
00056 * The function goes over all formats and compares it with format from cbor structure.
00057 *
00058 * @param data_cb[in]         The cbor text structure
00059 * @param data_format[out]    The format of data
00060 *
00061 * @return
00062 *     true for success, false otherwise.
00063 */
00064 static bool get_data_format(const cn_cbor *data_cb, fcc_bundle_data_format_e *data_format)
00065 {
00066 
00067     int data_format_index;
00068     bool res;
00069 
00070     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00071     SA_PV_ERR_RECOVERABLE_RETURN_IF((data_cb == NULL), false, "data_cb is null");
00072     SA_PV_ERR_RECOVERABLE_RETURN_IF((data_format == NULL), false, "data_format is null");
00073     SA_PV_ERR_RECOVERABLE_RETURN_IF((*data_format != FCC_INVALID_DATA_FORMAT), false, "wrong data format value");
00074 
00075     for (data_format_index = 0; data_format_index < FCC_MAX_DATA_FORMAT - 1; data_format_index++) {
00076         res = is_memory_equal(fcc_bundle_data_format_lookup_table[data_format_index].data_format_name,
00077                               strlen(fcc_bundle_data_format_lookup_table[data_format_index].data_format_name),
00078                               data_cb->v.bytes,
00079                               (size_t)(data_cb->length));
00080         if (res) {
00081             *data_format = fcc_bundle_data_format_lookup_table[data_format_index].data_format_type;
00082             return true;
00083         }
00084     }
00085     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00086     return false;
00087 }
00088 
00089 bool get_data_buffer_from_cbor(const cn_cbor *data_cb, uint8_t **out_data_buffer, size_t *out_size)
00090 {
00091 
00092     cn_cbor_type cb_type;
00093 
00094     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00095     SA_PV_ERR_RECOVERABLE_RETURN_IF((data_cb == NULL), false, "key_data_cb is null");
00096     SA_PV_ERR_RECOVERABLE_RETURN_IF((out_size == NULL), false, "Size buffer is null ");
00097     SA_PV_ERR_RECOVERABLE_RETURN_IF((out_data_buffer == NULL), false, "Data buffer is null");
00098     cb_type = data_cb->type;
00099 
00100     switch (cb_type) {
00101         case CN_CBOR_TAG:
00102             *out_data_buffer = (uint8_t*)data_cb->first_child->v.bytes;
00103             *out_size = (size_t)data_cb->first_child->length;
00104             break;
00105         case CN_CBOR_TEXT:
00106         case CN_CBOR_BYTES:
00107             *out_data_buffer = (uint8_t*)data_cb->v.bytes;
00108             *out_size = (size_t)(data_cb->length);
00109             break;
00110         case CN_CBOR_UINT:
00111             *out_data_buffer = (uint8_t*)(&(data_cb->v.uint));
00112             *out_size = (size_t)(data_cb->length);
00113             break;
00114         case CN_CBOR_INT:
00115             *out_data_buffer = (uint8_t*)(&(data_cb->v.sint));
00116             *out_size = (size_t)(data_cb->length);
00117             break;
00118         default:
00119             SA_PV_LOG_ERR("Invalid cbor data type (%u)!", data_cb->type);
00120             return false;
00121     }
00122     SA_PV_LOG_TRACE_FUNC_EXIT("out_size=%" PRIu32 "", (uint32_t)*out_size);
00123     return true;
00124 }
00125 /** Frees all allocated memory of data parameter struct and sets initial values.
00126 *
00127 * @param data_param[in/out]    The data parameter structure
00128 */
00129 void fcc_bundle_clean_and_free_data_param(fcc_bundle_data_param_s *data_param)
00130 {
00131     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00132 
00133     if (data_param->name != NULL) {
00134         fcc_free(data_param->name);
00135         data_param->name = NULL;
00136     }
00137 
00138     data_param->array_cn = NULL;
00139 
00140     //FIXME - in case we will support pem, add additional pointer data_der, that will point to allocated
00141     // memory and will always released in case not NULL nad data pointer will relate to user buffer allways.
00142     /*if (data_param->data_der != NULL) {
00143     fcc_stats_free(data_param->data_der);
00144     data_param->data_der = NULL;
00145     }*/
00146 
00147     memset(data_param, 0, sizeof(fcc_bundle_data_param_s));
00148     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00149 
00150 }
00151 bool fcc_bundle_get_data_param(const cn_cbor *data_param_cb, fcc_bundle_data_param_s *data_param)
00152 {
00153     bool status = false;
00154     int data_param_index = 0;
00155     cn_cbor *data_param_value_cb;
00156     fcc_bundle_data_param_type_e data_param_type;
00157 
00158     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00159 
00160     //Prepare key struct
00161     fcc_bundle_clean_and_free_data_param(data_param);
00162 
00163     //Go over all key's parameters and extract it to appropriate key struct member
00164     for (data_param_index = FCC_BUNDLE_DATA_PARAM_NAME_TYPE; data_param_index < FCC_BUNDLE_DATA_PARAM_MAX_TYPE; data_param_index++) {
00165 
00166         //Get value of parameter
00167         data_param_value_cb = cn_cbor_mapget_string(data_param_cb, fcc_bundle_data_param_lookup_table[data_param_index].data_param_name);
00168 
00169         if (data_param_value_cb != NULL) {
00170             //Get type of parameter
00171             data_param_type = fcc_bundle_data_param_lookup_table[data_param_index].data_param_type;
00172 
00173             switch (data_param_type) {
00174 
00175                 case FCC_BUNDLE_DATA_PARAM_NAME_TYPE:
00176                     status = get_data_name(data_param_value_cb, &(data_param->name), &(data_param->name_len));
00177                     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get data parameter name");
00178                     break;
00179 
00180                 case FCC_BUNDLE_DATA_PARAM_SCHEME_TYPE:
00181                     status = fcc_bundle_get_key_type(data_param_value_cb, (fcc_bundle_key_type_e*)&(data_param->type));
00182                     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get parameter type");
00183                     break;
00184 
00185                 case FCC_BUNDLE_DATA_PARAM_FORMAT_TYPE:
00186                     status = get_data_format(data_param_value_cb, (fcc_bundle_data_format_e*)&(data_param->format));
00187                     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get key format");
00188                     break;
00189 
00190                 case FCC_BUNDLE_DATA_PARAM_DATA_TYPE:
00191                     status = get_data_buffer_from_cbor(data_param_value_cb, &(data_param->data), &(data_param->data_size));
00192                     data_param->data_type = FCC_EXTERNAL_BUFFER_TYPE;
00193                     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get parameter data");
00194                     break;
00195                 case FCC_BUNDLE_DATA_PARAM_ARRAY_TYPE:
00196                     data_param->array_cn = data_param_value_cb;
00197                     break;
00198                 case FCC_BUNDLE_DATA_PARAM_ACL_TYPE:
00199                     status = get_data_buffer_from_cbor(data_param_value_cb, &(data_param->acl), &data_param->acl_size);
00200                     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get acl data");
00201                     break;
00202                 default:
00203                     SA_PV_ERR_RECOVERABLE_GOTO_IF((true), status = false, error_exit, "Parameter's field name is illegal");
00204             }//switch
00205         }//if
00206     }//for
00207 
00208     //FIXME: should be uncommented if PEM format is supported.
00209     /*
00210       if (data_param->format == FCC_PEM_DATA_FORMAT) {
00211           //status = convert_certificate_from_pem_to_der((uint8_t**)&(data_param->data), &(data_param->data_size));
00212           SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to convert the key from pem to der");
00213           //key->data_type = FCC_INTERNAL_BUFFER_TYPE;
00214       }
00215     */
00216 
00217     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00218     return status;
00219 
00220 error_exit:
00221     fcc_bundle_clean_and_free_data_param(data_param);
00222     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00223     return false;
00224 }
00225 
00226 fcc_status_e  fcc_bundle_process_sotp_buffer(cn_cbor *cbor_bytes, sotp_type_e sotp_type)
00227 {
00228     uint8_t *buf;
00229     size_t buf_size;
00230     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00231     bool status;
00232     char *sotp_type_name;
00233     size_t sotp_type_name_size = 0;
00234 
00235     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00236     
00237     fcc_status = fcc_get_sotp_type_name(sotp_type, &sotp_type_name, &sotp_type_name_size);
00238     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_PARAMETER,exit, "Failed to get sotp type name");
00239     SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_bytes->type != CN_CBOR_BYTES), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "cn_cbor object of incorrect type");
00240 
00241     status = get_data_buffer_from_cbor(cbor_bytes, &buf, &buf_size);
00242     SA_PV_ERR_RECOVERABLE_GOTO_IF((status == false), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Unable to retrieve data from cn_cbor");
00243 
00244     fcc_status = fcc_sotp_data_store(buf, buf_size, sotp_type);
00245     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_STORE_ERROR, exit, "Unable to store data to sotp");
00246 
00247 exit:
00248     if (fcc_status != FCC_STATUS_SUCCESS) {
00249         // In case of fcc_store_error_info failure we would still rather return the previous caught error.
00250         (void)fcc_store_error_info((const uint8_t*)sotp_type_name, sotp_type_name_size, fcc_status);
00251     }
00252     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00253     return fcc_status;
00254 }
00255 
00256 fcc_status_e  bundle_process_status_field(const cn_cbor *cbor_blob, char *cbor_group_name, size_t cbor_group_name_size, bool *fcc_field_status)
00257 {
00258     uint8_t *buff = NULL;
00259     size_t buff_size;
00260     uint32_t fcc_field_value;
00261     bool status;
00262     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00263 
00264     SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_blob == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid param cbor_blob");
00265     SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_blob->type != CN_CBOR_UINT), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Unexpected CBOR type");
00266 
00267     status = get_data_buffer_from_cbor(cbor_blob, &buff, &buff_size);
00268     SA_PV_ERR_RECOVERABLE_GOTO_IF((!status), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Unable to retrieve data from cn_cbor");
00269     SA_PV_ERR_RECOVERABLE_GOTO_IF((buff_size != sizeof(fcc_field_value)), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Incorrect buffer size for field value");
00270 
00271     memcpy(&fcc_field_value, buff, buff_size);
00272     SA_PV_ERR_RECOVERABLE_GOTO_IF(((fcc_field_value != 0) && (fcc_field_value != 1)), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit,"Unexpected value, should be either 0 or 1");
00273 
00274     if (fcc_field_value == 1) {
00275         *fcc_field_status = true;
00276     }
00277     else {
00278         *fcc_field_status = false;
00279     }
00280 
00281 exit:
00282     if (fcc_status != FCC_STATUS_SUCCESS)
00283     {
00284         // In case of fcc_store_error_info failure we would still rather return the previous caught error.
00285         (void)fcc_store_error_info((const uint8_t*)cbor_group_name, cbor_group_name_size, fcc_status);
00286     }
00287     return fcc_status;
00288 }
00289 
00290 
00291 fcc_status_e  fcc_bundle_factory_disable( void )
00292 {
00293 
00294     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00295 
00296     fcc_status = fcc_factory_disable();
00297     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to set factory disable flag");
00298 
00299 exit:
00300     if (fcc_status != FCC_STATUS_SUCCESS) {
00301         // In case of fcc_store_error_info failure we would still rather return the previous caught error.
00302         (void)fcc_store_error_info((const uint8_t*)g_sotp_factory_disable_type_name, strlen(g_sotp_factory_disable_type_name), fcc_status);
00303     }
00304     return fcc_status;
00305 }