leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Committer:
leothedragon
Date:
Tue May 04 08:55:12 2021 +0000
Revision:
0:8f0bb79ddd48
nmn

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:8f0bb79ddd48 1 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 2 // Copyright 2018 ARM Ltd.
leothedragon 0:8f0bb79ddd48 3 //
leothedragon 0:8f0bb79ddd48 4 // Licensed under the Apache License, Version 2.0 (the "License");
leothedragon 0:8f0bb79ddd48 5 // you may not use this file except in compliance with the License.
leothedragon 0:8f0bb79ddd48 6 // You may obtain a copy of the License at
leothedragon 0:8f0bb79ddd48 7 //
leothedragon 0:8f0bb79ddd48 8 // http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:8f0bb79ddd48 9 //
leothedragon 0:8f0bb79ddd48 10 // Unless required by applicable law or agreed to in writing, software
leothedragon 0:8f0bb79ddd48 11 // distributed under the License is distributed on an "AS IS" BASIS,
leothedragon 0:8f0bb79ddd48 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:8f0bb79ddd48 13 // See the License for the specific language governing permissions and
leothedragon 0:8f0bb79ddd48 14 // limitations under the License.
leothedragon 0:8f0bb79ddd48 15 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 16
leothedragon 0:8f0bb79ddd48 17
leothedragon 0:8f0bb79ddd48 18 #include "CertificateEnrollmentClient.h"
leothedragon 0:8f0bb79ddd48 19 #include "mbed-client/m2mresource.h"
leothedragon 0:8f0bb79ddd48 20 #include "mbed-client/m2minterfacefactory.h"
leothedragon 0:8f0bb79ddd48 21 #include "mbed-client/m2minterface.h"
leothedragon 0:8f0bb79ddd48 22 #include "pal.h"
leothedragon 0:8f0bb79ddd48 23 #include "eventOS_scheduler.h"
leothedragon 0:8f0bb79ddd48 24 #include "eventOS_event.h"
leothedragon 0:8f0bb79ddd48 25 #include "ce_defs.h"
leothedragon 0:8f0bb79ddd48 26 #include "ce_tlv.h"
leothedragon 0:8f0bb79ddd48 27 #include "certificate_enrollment.h"
leothedragon 0:8f0bb79ddd48 28 #include <stdio.h>
leothedragon 0:8f0bb79ddd48 29 #include <string.h>
leothedragon 0:8f0bb79ddd48 30 #include "CertificateEnrollmentClient.h"
leothedragon 0:8f0bb79ddd48 31 #include "CertificateEnrollmentClientCommon.h"
leothedragon 0:8f0bb79ddd48 32 #include "CertificateRenewalData.h"
leothedragon 0:8f0bb79ddd48 33 #include "pv_error_handling.h"
leothedragon 0:8f0bb79ddd48 34 #include "pv_macros.h"
leothedragon 0:8f0bb79ddd48 35
leothedragon 0:8f0bb79ddd48 36 #define RESOURCE_ID_CERTIFICATE_NAME "27002"
leothedragon 0:8f0bb79ddd48 37 #define OBJECT_LWM2M_CERTIFICATE "35011"
leothedragon 0:8f0bb79ddd48 38
leothedragon 0:8f0bb79ddd48 39 #define NUMBER_OF_CONCURRENT_RENEWALS 1
leothedragon 0:8f0bb79ddd48 40
leothedragon 0:8f0bb79ddd48 41
leothedragon 0:8f0bb79ddd48 42 /************************************************************************/
leothedragon 0:8f0bb79ddd48 43 /* Different calls to update */
leothedragon 0:8f0bb79ddd48 44 /************************************************************************/
leothedragon 0:8f0bb79ddd48 45
leothedragon 0:8f0bb79ddd48 46 extern const char g_lwm2m_name[];
leothedragon 0:8f0bb79ddd48 47
leothedragon 0:8f0bb79ddd48 48 namespace CertificateEnrollmentClient {
leothedragon 0:8f0bb79ddd48 49
leothedragon 0:8f0bb79ddd48 50 // Event type that is part of the arm_event_s structure.
leothedragon 0:8f0bb79ddd48 51 enum event_type_e {
leothedragon 0:8f0bb79ddd48 52 EVENT_TYPE_INIT, // Some initializer - nothing done currently, initialization called by mbed cloud client
leothedragon 0:8f0bb79ddd48 53 EVENT_TYPE_RENEWAL_REQUEST, // Certificate renewal request. We can tell if it is initiated by the server or the device with the derived type of CertificateRenewalDataBase of the certificate descriptor / global variable
leothedragon 0:8f0bb79ddd48 54 EVENT_TYPE_EST_RESPONDED, // Certificate arrived from EST service, or EST failure
leothedragon 0:8f0bb79ddd48 55 EVENT_TYPE_MAX = 0xff // Must fit in a uint8_t (field in the arm_event_s struct)
leothedragon 0:8f0bb79ddd48 56 };
leothedragon 0:8f0bb79ddd48 57
leothedragon 0:8f0bb79ddd48 58 // Pointer to the EST client object for dealing with the EST service.
leothedragon 0:8f0bb79ddd48 59 extern const CERT_ENROLLMENT_EST_CLIENT *g_est_client;
leothedragon 0:8f0bb79ddd48 60
leothedragon 0:8f0bb79ddd48 61 // Data for certificate that is currently being renewed. Will change to list if we need to support multiple renewals
leothedragon 0:8f0bb79ddd48 62 static CertificateRenewalDataBase *current_cert = NULL;
leothedragon 0:8f0bb79ddd48 63
leothedragon 0:8f0bb79ddd48 64 // ID of the handler we register to the MbedCloudClient event loop
leothedragon 0:8f0bb79ddd48 65 static int8_t handler_id = -1;
leothedragon 0:8f0bb79ddd48 66
leothedragon 0:8f0bb79ddd48 67 // Flag that indicates whether the module is initialized
leothedragon 0:8f0bb79ddd48 68 static bool is_initialized = false;
leothedragon 0:8f0bb79ddd48 69
leothedragon 0:8f0bb79ddd48 70 // Semaphore for enforcing that only NUMBER_OF_CONCURRENT_RENEWALS (currently 1) request at a time may update current_cert. Hold lock until process finished.
leothedragon 0:8f0bb79ddd48 71 // Important: When pal_osSemaphoreWait called from within event loop - do not block, must set timeout to 0, and fail if failed to acquire lock
leothedragon 0:8f0bb79ddd48 72 // Future: For supporting renewals of NUMBER_OF_CONCURRENT_RENEWALS certificates simultaneously - change to semaphore that counts to NUMBER_OF_CONCURRENT_RENEWALS
leothedragon 0:8f0bb79ddd48 73 // and maintain a list of certificates of size NUMBER_OF_CONCURRENT_RENEWALS inside the event loop.
leothedragon 0:8f0bb79ddd48 74 static palSemaphoreID_t g_renewal_sem = 0;
leothedragon 0:8f0bb79ddd48 75
leothedragon 0:8f0bb79ddd48 76
leothedragon 0:8f0bb79ddd48 77 /**
leothedragon 0:8f0bb79ddd48 78 * \brief Finish the renewal process.
leothedragon 0:8f0bb79ddd48 79 * Zero current_cert pointer, then release the semaphore. Note that when the semaphore is released - new device renewals may be made.
leothedragon 0:8f0bb79ddd48 80 * Then call renewal_data->finish() and delete renewal_data.
leothedragon 0:8f0bb79ddd48 81 *
leothedragon 0:8f0bb79ddd48 82 * \param renewal_data the data of the certificate to be renewed.
leothedragon 0:8f0bb79ddd48 83 * It is important that this is passed to the function because after releasing the semaphore - the global pointer may be replaced.
leothedragon 0:8f0bb79ddd48 84 * \param exit_status the status of the renewal process
leothedragon 0:8f0bb79ddd48 85 */
leothedragon 0:8f0bb79ddd48 86 static void certificate_renewal_finish(CertificateRenewalDataBase *renewal_data, ce_status_e exit_status);
leothedragon 0:8f0bb79ddd48 87
leothedragon 0:8f0bb79ddd48 88 /**
leothedragon 0:8f0bb79ddd48 89 * \brief The function that handles all the CertificateEnrollmentClient events
leothedragon 0:8f0bb79ddd48 90 * Create an arm_event_s object and call eventOS_event_send()
leothedragon 0:8f0bb79ddd48 91 * The event will have an application level priority, and will be executed when in the head of the event queue.
leothedragon 0:8f0bb79ddd48 92 * In the future: an extra arg should be passed - some descriptor for the specific CertificateRenewalDataBase object.
leothedragon 0:8f0bb79ddd48 93 *
leothedragon 0:8f0bb79ddd48 94 * \param event_type An event identifier
leothedragon 0:8f0bb79ddd48 95 */
leothedragon 0:8f0bb79ddd48 96 static void event_handler(arm_event_s* event);
leothedragon 0:8f0bb79ddd48 97
leothedragon 0:8f0bb79ddd48 98 /**
leothedragon 0:8f0bb79ddd48 99 * \brief Send a new event to the event loop queue.
leothedragon 0:8f0bb79ddd48 100 * Create an arm_event_s object and call eventOS_event_send()
leothedragon 0:8f0bb79ddd48 101 * The event will have an application level priority
leothedragon 0:8f0bb79ddd48 102 *
leothedragon 0:8f0bb79ddd48 103 * \param renewal_data A pointer to an object derived from CertificateRenewalDataBase
leothedragon 0:8f0bb79ddd48 104 * \param event_type An event identifier
leothedragon 0:8f0bb79ddd48 105 */
leothedragon 0:8f0bb79ddd48 106 static ce_status_e schedule_event(event_type_e event_type);
leothedragon 0:8f0bb79ddd48 107
leothedragon 0:8f0bb79ddd48 108 /**
leothedragon 0:8f0bb79ddd48 109 * \brief Callback that will be executed when an EST service response is available
leothedragon 0:8f0bb79ddd48 110 * Event Context is probably network so this function will check if response is success, if so, allocate the data if needed in renewal_data->est_data. schedule a new event with type EVENT_TYPE_EST_RESPONDED.
leothedragon 0:8f0bb79ddd48 111 *
leothedragon 0:8f0bb79ddd48 112 * \param result Whether the EST client successfully received a certificate from the EST service
leothedragon 0:8f0bb79ddd48 113 * \param cert_chain structure containing the certificate/chain received from the EST service
leothedragon 0:8f0bb79ddd48 114 * \param Context passed when requesting a certificate via the EST client. Currently unused. In the future will be used to identify the relevant CertificateRenewalDataBase object.
leothedragon 0:8f0bb79ddd48 115 */
leothedragon 0:8f0bb79ddd48 116 static void est_cb(est_enrollment_result_e result,
leothedragon 0:8f0bb79ddd48 117 cert_chain_context_s *cert_chain,
leothedragon 0:8f0bb79ddd48 118 void *context);
leothedragon 0:8f0bb79ddd48 119
leothedragon 0:8f0bb79ddd48 120 /**
leothedragon 0:8f0bb79ddd48 121 * \brief The function that handles the EST response.
leothedragon 0:8f0bb79ddd48 122 *
leothedragon 0:8f0bb79ddd48 123 * Called by event_handler(). renewal_data->est_data already exists and is valid.
leothedragon 0:8f0bb79ddd48 124 * Will perform a safe replacement of the certificate with the new certificate received from EST
leothedragon 0:8f0bb79ddd48 125 * Then it will free the EST chain and finish the renewal operation.
leothedragon 0:8f0bb79ddd48 126 * \param renewal_data A pointer to an object derived from CertificateRenewalDataBase
leothedragon 0:8f0bb79ddd48 127 */
leothedragon 0:8f0bb79ddd48 128 static void est_response_process(CertificateRenewalDataBase *renewal_data);
leothedragon 0:8f0bb79ddd48 129
leothedragon 0:8f0bb79ddd48 130 /**
leothedragon 0:8f0bb79ddd48 131 * \brief Create g_cert_enroll_lwm2m_obj, from the object create an object resource, and create the resources. Then push the object to the MCC object list
leothedragon 0:8f0bb79ddd48 132 *
leothedragon 0:8f0bb79ddd48 133 * Note that the pointers to the objects created by this function is owned by the CertificateEnrollmentClient Module and must be released in by CertificateEnrollmentClient::finalize()
leothedragon 0:8f0bb79ddd48 134 * \param list A reference to the MbedCloudClient object list. MbedCloudClient will later set the resource
leothedragon 0:8f0bb79ddd48 135 */
leothedragon 0:8f0bb79ddd48 136 static ce_status_e init_objects(M2MBaseList& list);
leothedragon 0:8f0bb79ddd48 137
leothedragon 0:8f0bb79ddd48 138 /**
leothedragon 0:8f0bb79ddd48 139 * \brief Release the objects created by init_objects()
leothedragon 0:8f0bb79ddd48 140 *
leothedragon 0:8f0bb79ddd48 141 */
leothedragon 0:8f0bb79ddd48 142 static void release_objects();
leothedragon 0:8f0bb79ddd48 143
leothedragon 0:8f0bb79ddd48 144 // Callback is called when we get a POST message to g_cert_enroll_lwm2m_resource (runs in high priority context!)
leothedragon 0:8f0bb79ddd48 145 /**
leothedragon 0:8f0bb79ddd48 146 * \brief Callback is called when we get a POST message to g_cert_enroll_lwm2m_resource
leothedragon 0:8f0bb79ddd48 147 * Runs in network context of the event loop.
leothedragon 0:8f0bb79ddd48 148 * This function extracts the input data, creates a CertificateEnrollmentClient::CertificateRenewalDataFromServer object sets the global variable
leothedragon 0:8f0bb79ddd48 149 *
leothedragon 0:8f0bb79ddd48 150 * \param arg a M2MResource::M2MExecuteParameter argument.
leothedragon 0:8f0bb79ddd48 151 */
leothedragon 0:8f0bb79ddd48 152 static void certificate_renewal_post(void *arg);
leothedragon 0:8f0bb79ddd48 153
leothedragon 0:8f0bb79ddd48 154 /**
leothedragon 0:8f0bb79ddd48 155 * \brief Start the renewal process.
leothedragon 0:8f0bb79ddd48 156 * Parse the certificate name, generate keys and CSR. Then call the EST client so the new certificate may be retrieved
leothedragon 0:8f0bb79ddd48 157 *
leothedragon 0:8f0bb79ddd48 158 * \param renewal_data the data of the certificate to be renewed
leothedragon 0:8f0bb79ddd48 159 */
leothedragon 0:8f0bb79ddd48 160 static void certificate_renewal_start(CertificateRenewalDataBase *renewal_data);
leothedragon 0:8f0bb79ddd48 161
leothedragon 0:8f0bb79ddd48 162 /**
leothedragon 0:8f0bb79ddd48 163 * \brief Call the user callback and send a response to the server, when a CertificateRenewalDataFromServer object does not exist.
leothedragon 0:8f0bb79ddd48 164 * Use only for server initiated renewal, since this sends a response to the server.
leothedragon 0:8f0bb79ddd48 165 *
leothedragon 0:8f0bb79ddd48 166 * \param tlv the raw data from the server - should be in the form of TLV
leothedragon 0:8f0bb79ddd48 167 * \param tlv_size size of the TLV buffer
leothedragon 0:8f0bb79ddd48 168 * \param ret_status The return status to return to the user callback and the server
leothedragon 0:8f0bb79ddd48 169 */
leothedragon 0:8f0bb79ddd48 170 static void call_user_cb_send_response(const uint8_t *tlv, uint16_t tlv_size, ce_status_e ret_status);
leothedragon 0:8f0bb79ddd48 171
leothedragon 0:8f0bb79ddd48 172 #ifdef CERT_RENEWAL_TEST
leothedragon 0:8f0bb79ddd48 173 void testonly_certificate_renewal_post(void *arg);
leothedragon 0:8f0bb79ddd48 174 #endif // CERT_RENEWAL_TEST
leothedragon 0:8f0bb79ddd48 175
leothedragon 0:8f0bb79ddd48 176 }
leothedragon 0:8f0bb79ddd48 177
leothedragon 0:8f0bb79ddd48 178 // FIXME: print error
leothedragon 0:8f0bb79ddd48 179 void CertificateEnrollmentClient::call_user_cb_send_response(const uint8_t *tlv, uint16_t tlv_size, ce_status_e ret_status)
leothedragon 0:8f0bb79ddd48 180 {
leothedragon 0:8f0bb79ddd48 181 CertificateEnrollmentClient::CertificateRenewalDataFromServer temp_obj(tlv, tlv_size);
leothedragon 0:8f0bb79ddd48 182 (void)temp_obj.parse();
leothedragon 0:8f0bb79ddd48 183
leothedragon 0:8f0bb79ddd48 184 // Call user callback with appropriate error
leothedragon 0:8f0bb79ddd48 185 // In case of parsing error (malformed TLV), the provided ret_status will be returned and not
leothedragon 0:8f0bb79ddd48 186 call_user_cert_renewal_cb(temp_obj.cert_name, ret_status, CE_INITIATOR_SERVER);
leothedragon 0:8f0bb79ddd48 187
leothedragon 0:8f0bb79ddd48 188 // Send response to the server
leothedragon 0:8f0bb79ddd48 189 SA_PV_LOG_INFO("sending delayed response\n");
leothedragon 0:8f0bb79ddd48 190 g_cert_enroll_lwm2m_resource->set_value(ret_status);
leothedragon 0:8f0bb79ddd48 191 g_cert_enroll_lwm2m_resource->send_delayed_post_response();
leothedragon 0:8f0bb79ddd48 192 }
leothedragon 0:8f0bb79ddd48 193
leothedragon 0:8f0bb79ddd48 194 void CertificateEnrollmentClient::certificate_renewal_post(void *arg)
leothedragon 0:8f0bb79ddd48 195 {
leothedragon 0:8f0bb79ddd48 196 palStatus_t pal_status;
leothedragon 0:8f0bb79ddd48 197 ce_status_e status;
leothedragon 0:8f0bb79ddd48 198 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 199
leothedragon 0:8f0bb79ddd48 200 M2MResource::M2MExecuteParameter *args = (M2MResource::M2MExecuteParameter *)arg;
leothedragon 0:8f0bb79ddd48 201 const uint8_t *data = args->get_argument_value();
leothedragon 0:8f0bb79ddd48 202 const uint16_t data_size = args->get_argument_value_length();
leothedragon 0:8f0bb79ddd48 203
leothedragon 0:8f0bb79ddd48 204 // If CEC module is not initialized - do not even take semaphore - exit with proper response
leothedragon 0:8f0bb79ddd48 205 SA_PV_ERR_RECOVERABLE_RETURN_IF((!is_initialized), call_user_cb_send_response(data, data_size, CE_STATUS_NOT_INITIALIZED), "Certificate Renewal module not initialized");
leothedragon 0:8f0bb79ddd48 206
leothedragon 0:8f0bb79ddd48 207 pal_status = pal_osSemaphoreWait(g_renewal_sem, 0, NULL);
leothedragon 0:8f0bb79ddd48 208
leothedragon 0:8f0bb79ddd48 209 if (pal_status == PAL_SUCCESS) {
leothedragon 0:8f0bb79ddd48 210 CertificateEnrollmentClient::current_cert = new CertificateEnrollmentClient::CertificateRenewalDataFromServer(data, data_size);
leothedragon 0:8f0bb79ddd48 211 if (!CertificateEnrollmentClient::current_cert) {
leothedragon 0:8f0bb79ddd48 212 status = CE_STATUS_OUT_OF_MEMORY;
leothedragon 0:8f0bb79ddd48 213 pal_status = pal_osSemaphoreRelease(g_renewal_sem);
leothedragon 0:8f0bb79ddd48 214 if (PAL_SUCCESS != pal_status) { // Should never happen
leothedragon 0:8f0bb79ddd48 215 status = CE_STATUS_ERROR;
leothedragon 0:8f0bb79ddd48 216 }
leothedragon 0:8f0bb79ddd48 217
leothedragon 0:8f0bb79ddd48 218 call_user_cb_send_response(data, data_size, status);
leothedragon 0:8f0bb79ddd48 219 return;
leothedragon 0:8f0bb79ddd48 220 }
leothedragon 0:8f0bb79ddd48 221
leothedragon 0:8f0bb79ddd48 222 // Enqueue the event
leothedragon 0:8f0bb79ddd48 223 status = schedule_event(CertificateEnrollmentClient::EVENT_TYPE_RENEWAL_REQUEST);
leothedragon 0:8f0bb79ddd48 224 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != CE_STATUS_SUCCESS), certificate_renewal_finish(CertificateEnrollmentClient::current_cert, status), "Error scheduling event");
leothedragon 0:8f0bb79ddd48 225
leothedragon 0:8f0bb79ddd48 226 } else {
leothedragon 0:8f0bb79ddd48 227 SA_PV_LOG_ERR("Failed to take semaphore- device busy\n");
leothedragon 0:8f0bb79ddd48 228
leothedragon 0:8f0bb79ddd48 229 if (pal_status == PAL_ERR_RTOS_TIMEOUT) {
leothedragon 0:8f0bb79ddd48 230 status = CE_STATUS_DEVICE_BUSY;
leothedragon 0:8f0bb79ddd48 231 } else {
leothedragon 0:8f0bb79ddd48 232 status = CE_STATUS_ERROR;
leothedragon 0:8f0bb79ddd48 233 }
leothedragon 0:8f0bb79ddd48 234
leothedragon 0:8f0bb79ddd48 235 call_user_cb_send_response(data, data_size, status);
leothedragon 0:8f0bb79ddd48 236 return;
leothedragon 0:8f0bb79ddd48 237 }
leothedragon 0:8f0bb79ddd48 238
leothedragon 0:8f0bb79ddd48 239 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 240 }
leothedragon 0:8f0bb79ddd48 241
leothedragon 0:8f0bb79ddd48 242 ce_status_e CertificateEnrollmentClient::certificate_renew(const char *cert_name)
leothedragon 0:8f0bb79ddd48 243 {
leothedragon 0:8f0bb79ddd48 244 palStatus_t pal_status = PAL_SUCCESS;
leothedragon 0:8f0bb79ddd48 245 ce_status_e status = CE_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 246
leothedragon 0:8f0bb79ddd48 247 SA_PV_ERR_RECOVERABLE_RETURN_IF((!cert_name), CE_STATUS_INVALID_PARAMETER, "Provided NULL certificate name");
leothedragon 0:8f0bb79ddd48 248 SA_PV_ERR_RECOVERABLE_RETURN_IF((!is_initialized), CE_STATUS_NOT_INITIALIZED, "Certificate Renewal module not initialized");
leothedragon 0:8f0bb79ddd48 249
leothedragon 0:8f0bb79ddd48 250 SA_PV_LOG_INFO_FUNC_ENTER("cert_name = %s\n", cert_name);
leothedragon 0:8f0bb79ddd48 251
leothedragon 0:8f0bb79ddd48 252 pal_status = pal_osSemaphoreWait(g_renewal_sem, 0, NULL);
leothedragon 0:8f0bb79ddd48 253
leothedragon 0:8f0bb79ddd48 254 if (pal_status == PAL_SUCCESS) {
leothedragon 0:8f0bb79ddd48 255 CertificateEnrollmentClient::current_cert = new CertificateEnrollmentClient::CertificateRenewalDataFromDevice(cert_name);
leothedragon 0:8f0bb79ddd48 256 SA_PV_ERR_RECOVERABLE_GOTO_IF((!CertificateEnrollmentClient::current_cert), status = CE_STATUS_OUT_OF_MEMORY, ReleseSemReturn, "Allocation error");
leothedragon 0:8f0bb79ddd48 257
leothedragon 0:8f0bb79ddd48 258 // Enqueue the event
leothedragon 0:8f0bb79ddd48 259 status = schedule_event(CertificateEnrollmentClient::EVENT_TYPE_RENEWAL_REQUEST);
leothedragon 0:8f0bb79ddd48 260 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != CE_STATUS_SUCCESS), status = status, ReleseSemReturn, "Error scheduling event");
leothedragon 0:8f0bb79ddd48 261
leothedragon 0:8f0bb79ddd48 262 // If some error synchronous error has occurred before scheduling the event - release the semaphore we had just taken,
leothedragon 0:8f0bb79ddd48 263 // and then return the error without calling the user callback
leothedragon 0:8f0bb79ddd48 264 ReleseSemReturn:
leothedragon 0:8f0bb79ddd48 265 if (status != CE_STATUS_SUCCESS) {
leothedragon 0:8f0bb79ddd48 266 pal_status = pal_osSemaphoreRelease(g_renewal_sem);
leothedragon 0:8f0bb79ddd48 267 if (PAL_SUCCESS != pal_status) { // Should never happen
leothedragon 0:8f0bb79ddd48 268 status = CE_STATUS_ERROR;
leothedragon 0:8f0bb79ddd48 269 }
leothedragon 0:8f0bb79ddd48 270 }
leothedragon 0:8f0bb79ddd48 271
leothedragon 0:8f0bb79ddd48 272 } else {
leothedragon 0:8f0bb79ddd48 273 // return with appropriate error
leothedragon 0:8f0bb79ddd48 274 if (pal_status == PAL_ERR_RTOS_TIMEOUT) {
leothedragon 0:8f0bb79ddd48 275 status = CE_STATUS_DEVICE_BUSY;
leothedragon 0:8f0bb79ddd48 276 } else {
leothedragon 0:8f0bb79ddd48 277 status = CE_STATUS_ERROR;
leothedragon 0:8f0bb79ddd48 278 }
leothedragon 0:8f0bb79ddd48 279
leothedragon 0:8f0bb79ddd48 280 }
leothedragon 0:8f0bb79ddd48 281
leothedragon 0:8f0bb79ddd48 282 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 283 return status;
leothedragon 0:8f0bb79ddd48 284 }
leothedragon 0:8f0bb79ddd48 285
leothedragon 0:8f0bb79ddd48 286
leothedragon 0:8f0bb79ddd48 287 void CertificateEnrollmentClient::on_certificate_renewal(cert_renewal_cb_f user_cb)
leothedragon 0:8f0bb79ddd48 288 {
leothedragon 0:8f0bb79ddd48 289 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 290 CertificateEnrollmentClient::set_user_cert_renewal_cb(user_cb);
leothedragon 0:8f0bb79ddd48 291 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 292 }
leothedragon 0:8f0bb79ddd48 293
leothedragon 0:8f0bb79ddd48 294
leothedragon 0:8f0bb79ddd48 295 ce_status_e CertificateEnrollmentClient::init_objects(M2MBaseList& list)
leothedragon 0:8f0bb79ddd48 296 {
leothedragon 0:8f0bb79ddd48 297 M2MObjectInstance *cert_enroll_lwm2m_obj_instance;
leothedragon 0:8f0bb79ddd48 298
leothedragon 0:8f0bb79ddd48 299 ce_status_e ce_status = CE_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 300 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 301
leothedragon 0:8f0bb79ddd48 302 // Create the certificate enrollment resource
leothedragon 0:8f0bb79ddd48 303 g_cert_enroll_lwm2m_obj = M2MInterfaceFactory::create_object(OBJECT_LWM2M_CERTIFICATE);
leothedragon 0:8f0bb79ddd48 304 SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_cert_enroll_lwm2m_obj), CE_STATUS_ERROR, "Error creating LWM2M object");
leothedragon 0:8f0bb79ddd48 305
leothedragon 0:8f0bb79ddd48 306 // Create the instance
leothedragon 0:8f0bb79ddd48 307 cert_enroll_lwm2m_obj_instance = g_cert_enroll_lwm2m_obj->create_object_instance();
leothedragon 0:8f0bb79ddd48 308 SA_PV_ERR_RECOVERABLE_GOTO_IF((!cert_enroll_lwm2m_obj_instance), ce_status = CE_STATUS_ERROR, Cleanup, "Error creating LWM2M object instance");
leothedragon 0:8f0bb79ddd48 309
leothedragon 0:8f0bb79ddd48 310 // Create the resource
leothedragon 0:8f0bb79ddd48 311 g_cert_enroll_lwm2m_resource = cert_enroll_lwm2m_obj_instance->create_dynamic_resource(RESOURCE_ID_CERTIFICATE_NAME, "Enroll", M2MResourceInstance::INTEGER, false);
leothedragon 0:8f0bb79ddd48 312 SA_PV_ERR_RECOVERABLE_GOTO_IF((!g_cert_enroll_lwm2m_resource), ce_status = CE_STATUS_ERROR, Cleanup, "Error creating LWM2M resource");
leothedragon 0:8f0bb79ddd48 313
leothedragon 0:8f0bb79ddd48 314 // Allow POST operations
leothedragon 0:8f0bb79ddd48 315 g_cert_enroll_lwm2m_resource->set_operation(M2MBase::POST_ALLOWED);
leothedragon 0:8f0bb79ddd48 316
leothedragon 0:8f0bb79ddd48 317 // Set the resource callback
leothedragon 0:8f0bb79ddd48 318 SA_PV_ERR_RECOVERABLE_GOTO_IF((!g_cert_enroll_lwm2m_resource->set_execute_function(CertificateEnrollmentClient::certificate_renewal_post)),
leothedragon 0:8f0bb79ddd48 319 ce_status = CE_STATUS_ERROR, Cleanup, "Error resource callback");
leothedragon 0:8f0bb79ddd48 320
leothedragon 0:8f0bb79ddd48 321 // Enable sending of delayed responses
leothedragon 0:8f0bb79ddd48 322 g_cert_enroll_lwm2m_resource->set_delayed_response(true);
leothedragon 0:8f0bb79ddd48 323
leothedragon 0:8f0bb79ddd48 324 // Push the object to the list
leothedragon 0:8f0bb79ddd48 325 list.push_back(g_cert_enroll_lwm2m_obj);
leothedragon 0:8f0bb79ddd48 326
leothedragon 0:8f0bb79ddd48 327 Cleanup:
leothedragon 0:8f0bb79ddd48 328 if (ce_status != CE_STATUS_SUCCESS) {
leothedragon 0:8f0bb79ddd48 329 // Destroying the object will destroy all instances and resources associated with it
leothedragon 0:8f0bb79ddd48 330 delete g_cert_enroll_lwm2m_obj;
leothedragon 0:8f0bb79ddd48 331 g_cert_enroll_lwm2m_resource = NULL;
leothedragon 0:8f0bb79ddd48 332 }
leothedragon 0:8f0bb79ddd48 333
leothedragon 0:8f0bb79ddd48 334 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 335 return ce_status;
leothedragon 0:8f0bb79ddd48 336 }
leothedragon 0:8f0bb79ddd48 337
leothedragon 0:8f0bb79ddd48 338 void CertificateEnrollmentClient::release_objects()
leothedragon 0:8f0bb79ddd48 339 {
leothedragon 0:8f0bb79ddd48 340 delete g_cert_enroll_lwm2m_obj;
leothedragon 0:8f0bb79ddd48 341 g_cert_enroll_lwm2m_obj = NULL;
leothedragon 0:8f0bb79ddd48 342 }
leothedragon 0:8f0bb79ddd48 343
leothedragon 0:8f0bb79ddd48 344
leothedragon 0:8f0bb79ddd48 345 ce_status_e CertificateEnrollmentClient::init(M2MBaseList& list, const EstClient *est_client)
leothedragon 0:8f0bb79ddd48 346 {
leothedragon 0:8f0bb79ddd48 347 ce_status_e ce_status = CE_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 348 palStatus_t pal_status = PAL_SUCCESS;
leothedragon 0:8f0bb79ddd48 349
leothedragon 0:8f0bb79ddd48 350 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 351
leothedragon 0:8f0bb79ddd48 352 if (!is_initialized) {
leothedragon 0:8f0bb79ddd48 353
leothedragon 0:8f0bb79ddd48 354 // Init the LWM2M object and resource and push the object
leothedragon 0:8f0bb79ddd48 355 ce_status = init_objects(list);
leothedragon 0:8f0bb79ddd48 356 SA_PV_ERR_RECOVERABLE_RETURN_IF((ce_status != CE_STATUS_SUCCESS), ce_status, "Error initializing LWM2M object and resource");
leothedragon 0:8f0bb79ddd48 357
leothedragon 0:8f0bb79ddd48 358 // Put the handler creation in a critical code block for the case that this function is called after the start of the event loop
leothedragon 0:8f0bb79ddd48 359 eventOS_scheduler_mutex_wait();
leothedragon 0:8f0bb79ddd48 360 if (handler_id == -1) { // Register the handler only if it hadn't been registered before
leothedragon 0:8f0bb79ddd48 361 handler_id = eventOS_event_handler_create(CertificateEnrollmentClient::event_handler, EVENT_TYPE_INIT);
leothedragon 0:8f0bb79ddd48 362 SA_PV_ERR_RECOVERABLE_RETURN_IF((handler_id == -1), ce_status, "Error creating event handler");
leothedragon 0:8f0bb79ddd48 363 }
leothedragon 0:8f0bb79ddd48 364 eventOS_scheduler_mutex_release();
leothedragon 0:8f0bb79ddd48 365
leothedragon 0:8f0bb79ddd48 366 // Initialize the CE module
leothedragon 0:8f0bb79ddd48 367 ce_status = ce_init();
leothedragon 0:8f0bb79ddd48 368 SA_PV_ERR_RECOVERABLE_RETURN_IF((ce_status != CE_STATUS_SUCCESS), ce_status, "Error initializing CE module");
leothedragon 0:8f0bb79ddd48 369
leothedragon 0:8f0bb79ddd48 370 // Create the certificate renewal mutex
leothedragon 0:8f0bb79ddd48 371 pal_status = pal_osSemaphoreCreate(NUMBER_OF_CONCURRENT_RENEWALS, &g_renewal_sem);
leothedragon 0:8f0bb79ddd48 372 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), CE_STATUS_ERROR, "Error creating semaphore");
leothedragon 0:8f0bb79ddd48 373
leothedragon 0:8f0bb79ddd48 374 #ifdef CERT_ENROLLMENT_EST_MOCK
leothedragon 0:8f0bb79ddd48 375 PV_UNUSED_PARAM(est_client);
leothedragon 0:8f0bb79ddd48 376 g_est_client = new EstClientMock();
leothedragon 0:8f0bb79ddd48 377 SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_est_client), CE_STATUS_ERROR, "Error creating mock EST");
leothedragon 0:8f0bb79ddd48 378 #else
leothedragon 0:8f0bb79ddd48 379 g_est_client = est_client;
leothedragon 0:8f0bb79ddd48 380 #endif
leothedragon 0:8f0bb79ddd48 381
leothedragon 0:8f0bb79ddd48 382 is_initialized = true;
leothedragon 0:8f0bb79ddd48 383 }
leothedragon 0:8f0bb79ddd48 384
leothedragon 0:8f0bb79ddd48 385 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 386 return CE_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 387 }
leothedragon 0:8f0bb79ddd48 388
leothedragon 0:8f0bb79ddd48 389 void CertificateEnrollmentClient::finalize()
leothedragon 0:8f0bb79ddd48 390 {
leothedragon 0:8f0bb79ddd48 391 palStatus_t pal_status;
leothedragon 0:8f0bb79ddd48 392 // If module not initialized - do nothing
leothedragon 0:8f0bb79ddd48 393 if (is_initialized) {
leothedragon 0:8f0bb79ddd48 394 pal_status = pal_osSemaphoreDelete(&g_renewal_sem);
leothedragon 0:8f0bb79ddd48 395 if (pal_status != PAL_SUCCESS) {
leothedragon 0:8f0bb79ddd48 396 SA_PV_LOG_ERR("Error deleting semaphore");
leothedragon 0:8f0bb79ddd48 397 }
leothedragon 0:8f0bb79ddd48 398
leothedragon 0:8f0bb79ddd48 399 #ifdef CERT_ENROLLMENT_EST_MOCK
leothedragon 0:8f0bb79ddd48 400 delete g_est_client;
leothedragon 0:8f0bb79ddd48 401 #endif
leothedragon 0:8f0bb79ddd48 402 is_initialized = false;
leothedragon 0:8f0bb79ddd48 403
leothedragon 0:8f0bb79ddd48 404 // LWM2M objects, instances, and resources are deleted when MbedCloudClient is unregistered and ServiceClient::state_unregister() is called
leothedragon 0:8f0bb79ddd48 405 // Currently nothing to finalize for CE core module except for KCM. However we do not wish to finalize it it may be used by other resources
leothedragon 0:8f0bb79ddd48 406
leothedragon 0:8f0bb79ddd48 407 // Release our resources
leothedragon 0:8f0bb79ddd48 408 release_objects();
leothedragon 0:8f0bb79ddd48 409 }
leothedragon 0:8f0bb79ddd48 410 }
leothedragon 0:8f0bb79ddd48 411
leothedragon 0:8f0bb79ddd48 412 void CertificateEnrollmentClient::event_handler(arm_event_s* event)
leothedragon 0:8f0bb79ddd48 413 {
leothedragon 0:8f0bb79ddd48 414 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 415
leothedragon 0:8f0bb79ddd48 416 switch (event->event_type) {
leothedragon 0:8f0bb79ddd48 417 case EVENT_TYPE_INIT:
leothedragon 0:8f0bb79ddd48 418 // Nothing to do - ce module already initialized
leothedragon 0:8f0bb79ddd48 419 break;
leothedragon 0:8f0bb79ddd48 420 case EVENT_TYPE_RENEWAL_REQUEST:
leothedragon 0:8f0bb79ddd48 421 certificate_renewal_start(current_cert);
leothedragon 0:8f0bb79ddd48 422 break;
leothedragon 0:8f0bb79ddd48 423 case EVENT_TYPE_EST_RESPONDED:
leothedragon 0:8f0bb79ddd48 424 est_response_process(current_cert);
leothedragon 0:8f0bb79ddd48 425 break;
leothedragon 0:8f0bb79ddd48 426 default:
leothedragon 0:8f0bb79ddd48 427 // Should never happen
leothedragon 0:8f0bb79ddd48 428 SA_PV_LOG_ERR("Unsuupported event\n");
leothedragon 0:8f0bb79ddd48 429 }
leothedragon 0:8f0bb79ddd48 430
leothedragon 0:8f0bb79ddd48 431 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 432 }
leothedragon 0:8f0bb79ddd48 433
leothedragon 0:8f0bb79ddd48 434 // This is the entry point of the renewal request, inside the event loop
leothedragon 0:8f0bb79ddd48 435 void CertificateEnrollmentClient::certificate_renewal_start(CertificateRenewalDataBase *renewal_data)
leothedragon 0:8f0bb79ddd48 436 {
leothedragon 0:8f0bb79ddd48 437 ce_status_e ce_status;
leothedragon 0:8f0bb79ddd48 438 est_status_e est_status;
leothedragon 0:8f0bb79ddd48 439 const char *cert_name;
leothedragon 0:8f0bb79ddd48 440 size_t cert_name_size;
leothedragon 0:8f0bb79ddd48 441 kcm_status_e kcm_status;
leothedragon 0:8f0bb79ddd48 442 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 443
leothedragon 0:8f0bb79ddd48 444 // Parse the certificate name
leothedragon 0:8f0bb79ddd48 445 ce_status = renewal_data->parse();
leothedragon 0:8f0bb79ddd48 446 SA_PV_ERR_RECOVERABLE_RETURN_IF((ce_status != CE_STATUS_SUCCESS), certificate_renewal_finish(renewal_data, ce_status), "Parse error");
leothedragon 0:8f0bb79ddd48 447
leothedragon 0:8f0bb79ddd48 448 // Create CSR's key handle
leothedragon 0:8f0bb79ddd48 449 kcm_status = cs_ec_key_new(&renewal_data->key_handle);
leothedragon 0:8f0bb79ddd48 450
leothedragon 0:8f0bb79ddd48 451 // translate error to some CE native error
leothedragon 0:8f0bb79ddd48 452 ce_status = ce_error_handler(kcm_status);
leothedragon 0:8f0bb79ddd48 453 SA_PV_ERR_RECOVERABLE_RETURN_IF((ce_status != CE_STATUS_SUCCESS), certificate_renewal_finish(renewal_data, ce_status), "Failed creating new key handle");
leothedragon 0:8f0bb79ddd48 454
leothedragon 0:8f0bb79ddd48 455 // key handle is initialized in the base constructor
leothedragon 0:8f0bb79ddd48 456 ce_status = ce_generate_keys_and_create_csr_from_certificate(renewal_data->cert_name, renewal_data->key_handle, &renewal_data->csr, &renewal_data->csr_size);
leothedragon 0:8f0bb79ddd48 457 SA_PV_ERR_RECOVERABLE_RETURN_IF((ce_status != CE_STATUS_SUCCESS), certificate_renewal_finish(renewal_data, ce_status), "Keys/CSR generation error");
leothedragon 0:8f0bb79ddd48 458
leothedragon 0:8f0bb79ddd48 459 // Call the EST client
leothedragon 0:8f0bb79ddd48 460
leothedragon 0:8f0bb79ddd48 461 // If lwm2m device certificate - set cert name to NULL and request EST enrollment
leothedragon 0:8f0bb79ddd48 462 if (pv_str_equals(g_lwm2m_name, renewal_data->cert_name,(uint32_t)(strlen(g_lwm2m_name) + 1))) {
leothedragon 0:8f0bb79ddd48 463 SA_PV_LOG_INFO("Attempting to renew LwM2M device certificate\n");
leothedragon 0:8f0bb79ddd48 464 cert_name = NULL;
leothedragon 0:8f0bb79ddd48 465 cert_name_size = 0;
leothedragon 0:8f0bb79ddd48 466 } else {
leothedragon 0:8f0bb79ddd48 467 SA_PV_LOG_INFO("Attempting to renew a custom certificate\n");
leothedragon 0:8f0bb79ddd48 468 cert_name = renewal_data->cert_name;
leothedragon 0:8f0bb79ddd48 469 cert_name_size = strlen(renewal_data->cert_name);
leothedragon 0:8f0bb79ddd48 470 }
leothedragon 0:8f0bb79ddd48 471
leothedragon 0:8f0bb79ddd48 472 // Request a certificate from a CSR via the EST service
leothedragon 0:8f0bb79ddd48 473 est_status = g_est_client->est_request_enrollment(cert_name, cert_name_size, renewal_data->csr, renewal_data->csr_size, est_cb, NULL);
leothedragon 0:8f0bb79ddd48 474 // FIXME: Currently commented out. If we find that the CSR must be persistent only during est_request_enrollment call - uncomment, and this should be the only place we free the CSR
leothedragon 0:8f0bb79ddd48 475 //free(renewal_data->csr);
leothedragon 0:8f0bb79ddd48 476 SA_PV_ERR_RECOVERABLE_RETURN_IF((est_status != EST_STATUS_SUCCESS), certificate_renewal_finish(renewal_data, CE_STATUS_EST_ERROR), "EST request failed");
leothedragon 0:8f0bb79ddd48 477
leothedragon 0:8f0bb79ddd48 478 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 479 }
leothedragon 0:8f0bb79ddd48 480
leothedragon 0:8f0bb79ddd48 481 ce_status_e CertificateEnrollmentClient::schedule_event(event_type_e event_type)
leothedragon 0:8f0bb79ddd48 482 {
leothedragon 0:8f0bb79ddd48 483 int8_t event_status;
leothedragon 0:8f0bb79ddd48 484
leothedragon 0:8f0bb79ddd48 485 arm_event_s event = {
leothedragon 0:8f0bb79ddd48 486 .receiver = handler_id, // ID we got when creating our handler
leothedragon 0:8f0bb79ddd48 487 .sender = 0, // Which tasklet sent us the event is irrelevant to us
leothedragon 0:8f0bb79ddd48 488 .event_type = event_type, // Indicate event type
leothedragon 0:8f0bb79ddd48 489 .event_id = 0, // We currently do not need an ID for a specific event - event type is enough
leothedragon 0:8f0bb79ddd48 490 .data_ptr = 0, // Not needed, data handled in internal structure
leothedragon 0:8f0bb79ddd48 491 .priority = ARM_LIB_LOW_PRIORITY_EVENT, // Application level priority
leothedragon 0:8f0bb79ddd48 492 .event_data = 0, // With one certificate this is irrelevant. If allow multiple certificates, This will be a certificate descriptor (index in a CertificateRenewalDataBase list)
leothedragon 0:8f0bb79ddd48 493 };
leothedragon 0:8f0bb79ddd48 494
leothedragon 0:8f0bb79ddd48 495 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 496
leothedragon 0:8f0bb79ddd48 497 event_status = eventOS_event_send(&event);
leothedragon 0:8f0bb79ddd48 498 SA_PV_ERR_RECOVERABLE_RETURN_IF((event_status < 0), CE_STATUS_OUT_OF_MEMORY, "Error scheduling event");
leothedragon 0:8f0bb79ddd48 499
leothedragon 0:8f0bb79ddd48 500 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 501 return CE_STATUS_SUCCESS;
leothedragon 0:8f0bb79ddd48 502 }
leothedragon 0:8f0bb79ddd48 503
leothedragon 0:8f0bb79ddd48 504 void CertificateEnrollmentClient::est_cb(est_enrollment_result_e result,
leothedragon 0:8f0bb79ddd48 505 cert_chain_context_s *cert_chain,
leothedragon 0:8f0bb79ddd48 506 void *context)
leothedragon 0:8f0bb79ddd48 507 {
leothedragon 0:8f0bb79ddd48 508 ce_status_e status;
leothedragon 0:8f0bb79ddd48 509 SA_PV_LOG_INFO_FUNC_ENTER("result = %d", result);
leothedragon 0:8f0bb79ddd48 510
leothedragon 0:8f0bb79ddd48 511 PV_UNUSED_PARAM(context);
leothedragon 0:8f0bb79ddd48 512 if (result != EST_ENROLLMENT_SUCCESS || cert_chain == NULL) {
leothedragon 0:8f0bb79ddd48 513 return certificate_renewal_finish(current_cert, CE_STATUS_EST_ERROR);
leothedragon 0:8f0bb79ddd48 514 }
leothedragon 0:8f0bb79ddd48 515
leothedragon 0:8f0bb79ddd48 516 // Cert chain remains persistent until g_est_client->free_cert_chain_context is called
leothedragon 0:8f0bb79ddd48 517 current_cert->est_data = cert_chain;
leothedragon 0:8f0bb79ddd48 518
leothedragon 0:8f0bb79ddd48 519 status = schedule_event(CertificateEnrollmentClient::EVENT_TYPE_EST_RESPONDED);
leothedragon 0:8f0bb79ddd48 520 if (status != CE_STATUS_SUCCESS) { // If event scheduling fails - free the chain context and finish the process
leothedragon 0:8f0bb79ddd48 521 SA_PV_LOG_INFO("Error scheduling event");
leothedragon 0:8f0bb79ddd48 522 g_est_client->free_cert_chain_context(current_cert->est_data);
leothedragon 0:8f0bb79ddd48 523
leothedragon 0:8f0bb79ddd48 524 // Make sure we do not keep an invalid pointer
leothedragon 0:8f0bb79ddd48 525 current_cert->est_data = NULL;
leothedragon 0:8f0bb79ddd48 526 certificate_renewal_finish(current_cert, status);
leothedragon 0:8f0bb79ddd48 527 }
leothedragon 0:8f0bb79ddd48 528
leothedragon 0:8f0bb79ddd48 529 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 530 }
leothedragon 0:8f0bb79ddd48 531
leothedragon 0:8f0bb79ddd48 532 void CertificateEnrollmentClient::est_response_process(CertificateRenewalDataBase *renewal_data)
leothedragon 0:8f0bb79ddd48 533 {
leothedragon 0:8f0bb79ddd48 534 ce_status_e ce_status;
leothedragon 0:8f0bb79ddd48 535 ce_renewal_params_s params;
leothedragon 0:8f0bb79ddd48 536 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
leothedragon 0:8f0bb79ddd48 537
leothedragon 0:8f0bb79ddd48 538 // Fill params
leothedragon 0:8f0bb79ddd48 539 params.cert_data = renewal_data->est_data;
leothedragon 0:8f0bb79ddd48 540 params.crypto_handle = renewal_data->key_handle;
leothedragon 0:8f0bb79ddd48 541
leothedragon 0:8f0bb79ddd48 542 // Perform a safe renewal
leothedragon 0:8f0bb79ddd48 543 ce_status = ce_safe_renewal(renewal_data->cert_name, &params);
leothedragon 0:8f0bb79ddd48 544
leothedragon 0:8f0bb79ddd48 545 // Free the est chain. Do not free in the destructor, we'd rather free it as soon as possible
leothedragon 0:8f0bb79ddd48 546 g_est_client->free_cert_chain_context(renewal_data->est_data);
leothedragon 0:8f0bb79ddd48 547 renewal_data->est_data = NULL;
leothedragon 0:8f0bb79ddd48 548
leothedragon 0:8f0bb79ddd48 549 // Done!
leothedragon 0:8f0bb79ddd48 550 certificate_renewal_finish(renewal_data, ce_status);
leothedragon 0:8f0bb79ddd48 551 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 552 }
leothedragon 0:8f0bb79ddd48 553
leothedragon 0:8f0bb79ddd48 554 void CertificateEnrollmentClient::certificate_renewal_finish(CertificateRenewalDataBase *renewal_data, ce_status_e exit_status)
leothedragon 0:8f0bb79ddd48 555 {
leothedragon 0:8f0bb79ddd48 556 palStatus_t pal_status;
leothedragon 0:8f0bb79ddd48 557 SA_PV_LOG_INFO_FUNC_ENTER("exit_status = %d", exit_status);
leothedragon 0:8f0bb79ddd48 558
leothedragon 0:8f0bb79ddd48 559 // Don't leave an invalid global pointer
leothedragon 0:8f0bb79ddd48 560 current_cert = NULL;
leothedragon 0:8f0bb79ddd48 561
leothedragon 0:8f0bb79ddd48 562 // Note: release of the mutex is before the deletion of the object (which holds the allocated cert_name)
leothedragon 0:8f0bb79ddd48 563 // and before the user callback is invoked (so that the user may call the renewal API successfully from within his callback)
leothedragon 0:8f0bb79ddd48 564 pal_status = pal_osSemaphoreRelease(g_renewal_sem);
leothedragon 0:8f0bb79ddd48 565 if (PAL_SUCCESS != pal_status) { //
leothedragon 0:8f0bb79ddd48 566 exit_status = CE_STATUS_ERROR;
leothedragon 0:8f0bb79ddd48 567 }
leothedragon 0:8f0bb79ddd48 568
leothedragon 0:8f0bb79ddd48 569 // At this point, new device requests may be made and the global pointer CertificateEnrollmentClient::current_cert may be changed.
leothedragon 0:8f0bb79ddd48 570 // Therefore, we use the renewal_data pointer that was past as a parameter to this function
leothedragon 0:8f0bb79ddd48 571 // New server requests will not be made until after this function returns since the response to the server is enqueued into the event loop by renewal_data->finish()
leothedragon 0:8f0bb79ddd48 572 // and it is guaranteed that the server will not send another request until it receives a response.
leothedragon 0:8f0bb79ddd48 573 renewal_data->finish(exit_status);
leothedragon 0:8f0bb79ddd48 574
leothedragon 0:8f0bb79ddd48 575 delete renewal_data;
leothedragon 0:8f0bb79ddd48 576
leothedragon 0:8f0bb79ddd48 577 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
leothedragon 0:8f0bb79ddd48 578 }
leothedragon 0:8f0bb79ddd48 579
leothedragon 0:8f0bb79ddd48 580 #ifdef CERT_RENEWAL_TEST
leothedragon 0:8f0bb79ddd48 581 void CertificateEnrollmentClient::testonly_certificate_renewal_post(void *arg)
leothedragon 0:8f0bb79ddd48 582 {
leothedragon 0:8f0bb79ddd48 583 return certificate_renewal_post(arg);
leothedragon 0:8f0bb79ddd48 584 }
leothedragon 0:8f0bb79ddd48 585
leothedragon 0:8f0bb79ddd48 586
leothedragon 0:8f0bb79ddd48 587 #endif // CERT_RENEWAL_TEST