Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_uc_certificate_kcm_api.c Source File

arm_uc_certificate_kcm_api.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-control-center/arm_uc_certificate.h"
00020 #include "update-client-common/arm_uc_config.h"
00021 #include "update-client-common/arm_uc_crypto.h"
00022 
00023 #ifndef ARM_UC_USE_KCM
00024 #define ARM_UC_USE_KCM 0
00025 #endif
00026 
00027 #if ARM_UC_USE_KCM
00028 
00029 #include "key-config-manager/key_config_manager.h"
00030 
00031 static arm_uc_error_t kerr2ucerr(int kerr)
00032 {
00033     arm_uc_error_t err;
00034     switch(kerr)
00035     {
00036         case KCM_STATUS_SUCCESS:
00037             err.code = ARM_UC_CM_ERR_NONE;
00038             break;
00039         case KCM_STATUS_INVALID_PARAMETER:
00040             err.code = ARM_UC_CM_ERR_INVALID_PARAMETER;
00041             break;
00042         case KCM_STATUS_ITEM_NOT_FOUND:
00043         case KCM_STATUS_ESFS_ERROR:
00044             err.code = ARM_UC_CM_ERR_NOT_FOUND;
00045             break;
00046         case KCM_CRYPTO_STATUS_PARSING_DER_CERT:
00047             err.code = ARM_UC_CM_ERR_INVALID_CERT;
00048             break;
00049         case KCM_STATUS_OUT_OF_MEMORY:
00050         case KCM_STATUS_INSUFFICIENT_BUFFER:
00051         default:
00052             err.modulecc[0] = 'K';
00053             err.modulecc[1] = 'C';
00054             err.error       = kerr;
00055             break;
00056     }
00057     return err;
00058 }
00059 
00060 static arm_uc_error_t arm_uc_kcm_cert_fetcher(arm_uc_buffer_t* certificate,
00061     const arm_uc_buffer_t* fingerprint,
00062     const arm_uc_buffer_t* DERCertificateList,
00063     void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*, const arm_uc_buffer_t*))
00064 {
00065     uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT;
00066     // uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX;
00067     // uint8_t* b64hash = &certName[sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX)-1];
00068     // uint8_t defaultInUse = 0;
00069 
00070     UC_CONT_TRACE("Attempting to fetch certificate from: %s", certName);
00071     // Format the certificate name into the certName buffer
00072     // ARM_UC_Base64Enc(b64hash, sizeof(b64hash), fingerprint);
00073 
00074     // The arm_uc_buffer_t's size variable is 32bit, but kcm_item_get_data() needs
00075     // a pointer to size_t, so we need to use a temp variable for it or we would get
00076     // a corrupted arm_uc_buffer_t structure.
00077     size_t cert_data_size = 0;
00078 
00079     // Look up the certificate by fingerprint
00080     kcm_status_e  kerr = kcm_item_get_data(certName,
00081                                           strlen((char*)certName),
00082                                           KCM_CERTIFICATE_ITEM,
00083                                           certificate->ptr,
00084                                           certificate->size_max,
00085                                           &cert_data_size);
00086 
00087     // Check if the certificate was found.
00088     // if (kerr == KCM_STATUS_ITEM_NOT_FOUND || kerr == KCM_STATUS_ESFS_ERROR)
00089     // {
00090     //     printf("fingerprinted certificate not found. Checking for default...\n");
00091     //     // If not, try the default location.
00092     //     kerr = kcm_item_get_data(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT,
00093     //                              sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT) - 1,
00094     //                              KCM_CERTIFICATE_ITEM,
00095     //                              certificate->ptr,
00096     //                              certificate->size_max,
00097     //                              &cert_data_size);
00098     //     defaultInUse = 1;
00099     // }
00100     // Translate the KCM error to an update client error
00101     arm_uc_error_t err = kerr2ucerr(kerr);
00102     arm_uc_error_t errFinish = {ARM_UC_CM_ERR_INVALID_PARAMETER};
00103 
00104     // Prepare to calculate the fingerprint of the certificate.
00105     arm_uc_mdHandle_t h = { 0 };
00106     uint8_t fingerprintLocal[MBED_CLOUD_SHA256_BYTES];
00107     arm_uc_buffer_t fingerprintLocalBuffer = {
00108         .size_max = sizeof(fingerprintLocal),
00109         .size = 0,
00110         .ptr = fingerprintLocal};
00111 
00112     // Check for overflow before continuing. This is actually unnecessary
00113     // belts and suspenders type of code, as the max value given to kcm_item_get_data()
00114     // is at most UINT32_MAX, but the Coverity might point this as a error.
00115     if (cert_data_size <= UINT32_MAX)
00116     {
00117         certificate->size = (uint32_t)cert_data_size;
00118     }
00119     else
00120     {
00121         err.code = ARM_UC_CM_ERR_INVALID_CERT;
00122     }
00123 
00124     // Calculate the fingerprint of the certificate
00125     if (err.error == ERR_NONE)
00126     {
00127         err = ARM_UC_cryptoHashSetup(&h, ARM_UC_CU_SHA256);
00128     }
00129     if (err.error == ERR_NONE)
00130     {
00131         err = ARM_UC_cryptoHashUpdate(&h, certificate);
00132 
00133         // The cryptoHashFinish needs to be called no matter if the update succeeded or not as
00134         // it will do memory freeing. But in order to have valid result, the update & finish
00135         // must both have succeeded.
00136         errFinish = ARM_UC_cryptoHashFinish(&h, &fingerprintLocalBuffer);
00137 
00138         // Compare the calculated fingerprint to the requested fingerprint.
00139         if ((err.error == ERR_NONE) && (errFinish.error == ERR_NONE))
00140         {
00141             uint32_t rc = ARM_UC_BinCompareCT(fingerprint, &fingerprintLocalBuffer);
00142             if (rc)
00143             {
00144                 err.code = ARM_UC_CM_ERR_NOT_FOUND;
00145             }
00146             else
00147             {
00148                 UC_CONT_TRACE("Certificate lookup fingerprint matched.");
00149                 err.code = ARM_UC_CM_ERR_NONE;
00150             }
00151 
00152             if (callback && (err.error == ERR_NONE))
00153             {
00154                 callback(err, certificate, fingerprint);
00155             }
00156         }
00157     }
00158 
00159     return err;
00160 }
00161 
00162 static arm_uc_error_t arm_uc_kcm_cert_storer(
00163     const arm_uc_buffer_t* cert,
00164     const arm_uc_buffer_t* fingerprint,
00165     void(*callback)(arm_uc_error_t, const arm_uc_buffer_t*))
00166 {
00167     // uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX;
00168     // uint8_t* b64hash = &certName[sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX)-1];
00169     uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT;
00170 
00171     UC_CONT_TRACE("Storing certificate to: %s\n", certName);
00172     // ARM_UC_Base64Enc(b64hash, sizeof(b64hash), fingerprint);
00173 
00174     kcm_status_e  kerr = kcm_item_store(certName,
00175                                        strlen((char*) certName),
00176                                        KCM_CERTIFICATE_ITEM,
00177                                        true,
00178                                        cert->ptr,
00179                                        cert->size,
00180                                        NULL);
00181 
00182     arm_uc_error_t err = kerr2ucerr(kerr);
00183 
00184     if (callback && (err.code == ARM_UC_CM_ERR_NONE))
00185     {
00186         callback(err, fingerprint);
00187     }
00188 
00189     return err;
00190 }
00191 
00192 const struct arm_uc_certificate_api arm_uc_certificate_kcm_api = {
00193     .fetch = arm_uc_kcm_cert_fetcher,
00194     .store = arm_uc_kcm_cert_storer
00195 };
00196 
00197 #endif // ARM_UC_USE_KCM