a266426fc2c58d2fbc8639e0b3e91285a2e3eb20
[platform/upstream/iotivity.git] / service / easy-setup / mediator / richsdk / src / EnrolleeSecurity.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "base64.h"
22
23 #include "EnrolleeSecurity.h"
24 #include "oxmjustworks.h"
25 #include "oxmrandompin.h"
26 #include "EnrolleeResource.h"
27 #include "logger.h"
28 #include "ESException.h"
29 #include "oic_malloc.h"
30 #include "provisioningdatabasemanager.h"
31 #include "oic_string.h"
32 #include "utlist.h"
33 #include "srmutility.h"
34
35 namespace OIC
36 {
37     namespace Service
38     {
39         #define MAX_PERMISSION_LENGTH (5)
40         #define CREATE (1)
41         #define READ (2)
42         #define UPDATE (4)
43         #define DELETE (8)
44         #define NOTIFY (16)
45         #define DASH '-'
46
47         // TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
48         // The value should be accepted from the application as a parameter during ocplatform
49         // config call
50         #define ES_SEC_DISCOVERY_TIMEOUT 5
51
52         EnrolleeSecurity::EnrolleeSecurity(
53             std::shared_ptr< OC::OCResource > resource,
54             const std::string secDbPath)
55         {
56             (void) secDbPath;
57             m_ocResource = resource;
58         }
59
60         void EnrolleeSecurity::convertUUIDToString(const uint8_t uuid[UUID_SIZE],
61                                                               std::string& uuidString)
62         {
63             char uuidArray[UUID_STRING_SIZE] = {'\0',};
64             int ret = snprintf(uuidArray, UUID_STRING_SIZE,
65                     "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
66                     uuid[0], uuid[1], uuid[2], uuid[3],
67                     uuid[4], uuid[5], uuid[6], uuid[7],
68                     uuid[8], uuid[9], uuid[10], uuid[11],
69                     uuid[12], uuid[13], uuid[14], uuid[15]
70                     );
71
72             if (ret != UUID_STRING_SIZE - 1)
73             {
74                 return;
75             }
76
77             uuidString = uuidArray;
78         }
79
80         void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
81         {
82             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb IN");
83             if (hasError)
84             {
85                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransfer is failed with code(%d)", hasError);
86                 OTMResult = false;
87             }
88             else
89             {
90                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "OwnershipTransfer is succeeded");
91                 for (unsigned int i = 0; i < result->size(); i++)
92                 {
93                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device", result->at(i).res);
94                 }
95                 delete result;
96                 OTMResult = true;
97             }
98             m_cond.notify_all();
99         }
100
101         ESResult EnrolleeSecurity::provisionOwnership()
102         {
103             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionOwnership IN");
104
105             ESResult res = ESResult::ES_ERROR;
106
107             OCStackResult result = OC_STACK_ERROR;
108             OicUuid_t uuid;
109             if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
110             {
111                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
112                 return res;
113             }
114
115             result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
116                                                     &uuid,
117                                                     m_securedResource);
118             if (result != OC_STACK_OK)
119             {
120                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Secure Resource Discovery failed.");
121                 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
122                 return res;
123             }
124             else if (m_securedResource)
125             {
126                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
127                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", m_securedResource->getDevAddr().c_str());
128                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "SID: %s", m_securedResource->getDeviceID().c_str());
129                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", m_securedResource->getOwnedStatus());
130
131                 if (m_securedResource->getOwnedStatus()) // owned check logic
132                 {
133                     if(isOwnedDeviceRegisteredInSVRDB())
134                     {
135                         OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
136                                 "The found device is already owned by Mediator.(SUCCESS)");
137                         res = ESResult::ES_OK;
138                     }
139                     else
140                     {
141                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
142                         res = ESResult::ES_ERROR;
143                     }
144                     return res;
145                 }
146                 else // unowned check logic
147                 {
148                     if(isOwnedDeviceRegisteredInSVRDB())
149                     {
150                         OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
151                             "Found Unowned device's DevID at DB of ownedDevices list");
152
153                         OC::ResultCallBack removeDeviceWithUuidCB = std::bind(
154                                 &EnrolleeSecurity::removeDeviceWithUuidCB,
155                                 this, std::placeholders::_1, std::placeholders::_2);
156
157                         result = OCSecure::removeDeviceWithUuid(ES_SEC_DISCOVERY_TIMEOUT,
158                                                                 m_ocResource->sid(),
159                                                                 removeDeviceWithUuidCB);
160                         if(result != OC_STACK_OK)
161                         {
162                             OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid failed. (%d)", result);
163                             res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
164                             return res;
165                         }
166
167                         std::unique_lock<std::mutex> lck(m_mtx);
168                         m_cond.wait_for(lck, std::chrono::seconds(ES_SEC_DISCOVERY_TIMEOUT));
169
170                         if(!removeDeviceResult)
171                         {
172                             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Removing device is failed.");
173                             res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
174                             return res;
175                         }
176                         OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Removing device is succeeded.");
177                     }
178
179                     res = performOwnershipTransfer();
180
181                     if(res != ESResult::ES_OK)
182                     {
183                         OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed. (%d)", res);
184                         res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
185                         return res;
186                     }
187
188                     std::unique_lock<std::mutex> lck(m_mtx);
189                     m_cond.wait(lck);
190
191                     if(!OTMResult)
192                     {
193                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
194                         res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
195                     }
196                 }
197             }
198             else
199             {
200                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found.");
201                 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
202             }
203             return res;
204         }
205
206         ESResult EnrolleeSecurity::performOwnershipTransfer()
207         {
208             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performOwnershipTransfer IN.");
209
210             OCStackResult result = OC_STACK_ERROR;
211
212             OTMCallbackData_t justWorksCBData;
213             justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
214             justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
215             justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
216             justWorksCBData.createOwnerTransferPayloadCB =
217                     CreateJustWorksOwnerTransferPayload;
218             OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
219
220             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
221                     m_securedResource->getDeviceID().c_str());
222
223             OC::ResultCallBack ownershipTransferCb = std::bind(
224                     &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
225                     std::placeholders::_2);
226
227             result = m_securedResource->doOwnershipTransfer(ownershipTransferCb);
228             if (result != OC_STACK_OK)
229             {
230                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is failed");
231                 return ESResult::ES_ERROR;
232             }
233             return ESResult::ES_OK;
234         }
235
236         void EnrolleeSecurity::removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError)
237         {
238             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuidCB IN");
239
240             if (hasError)
241             {
242                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is failed with code (%d)", hasError);
243                removeDeviceResult = false;
244             }
245
246             else
247             {
248                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is succeeded");
249
250                for (unsigned int i = 0; i < result->size(); i++)
251                {
252                     std::string uuid;
253                     convertUUIDToString(result->at(i).deviceId.id, uuid);
254
255                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG,
256                         "Result is = %d for device %s",  result->at(i).res, uuid.c_str());
257                }
258                removeDeviceResult = true;
259             }
260             m_cond.notify_all();
261         }
262
263         bool EnrolleeSecurity::isOwnedDeviceRegisteredInSVRDB()
264         {
265             OCStackResult res = OC_STACK_ERROR;
266
267             OCUuidList_t *uuidList = NULL;
268             size_t numOfDevices = 0;
269
270             res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
271             if (OC_STACK_OK != res)
272             {
273                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while getting info from DB");
274                 return false;
275             }
276
277             OCUuidList_t *pUuidList = uuidList;
278             while (pUuidList)
279             {
280                 std::string uuid;
281                 convertUUIDToString(pUuidList->dev.id, uuid);
282                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG,
283                     "m_ocResource->sid(): %s, cur DB UUID %s",
284                     m_ocResource->sid().c_str(), uuid.c_str());
285                 if(m_ocResource->sid() == uuid.c_str())
286                 {
287                     OICFree(uuidList);
288                     return true;
289                 }
290                 pUuidList = pUuidList->next;
291             }
292             OICFree(uuidList);
293             return false;
294         }
295
296
297         std::string EnrolleeSecurity::getUUID() const
298         {
299             return m_ocResource->sid();
300         };
301
302 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
303         ESResult EnrolleeSecurity::provisionSecurityForCloudServer(
304             std::string cloudUuid, int credId)
305         {
306             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionSecurityForCloudServer IN");
307
308             ESResult res = ESResult::ES_ERROR;
309
310             // Need to discover Owned device in a given network, again
311             std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
312
313             OCStackResult result;
314             OicUuid_t uuid;
315             if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
316             {
317                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
318                 return res;
319             }
320
321
322             result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
323                                                     &uuid,
324                                                     ownedDevice);
325             if (result != OC_STACK_OK)
326             {
327                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "secureResource Discovery failed.");
328                 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
329                 return res;
330             }
331             else if (ownedDevice)
332             {
333                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
334                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", ownedDevice->getDevAddr().c_str());
335                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "SID: %s", ownedDevice->getDeviceID().c_str());
336                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", ownedDevice->getOwnedStatus());
337
338                 if (ownedDevice->getOwnedStatus())
339                 {
340                     if(!isOwnedDeviceRegisteredInSVRDB())
341                     {
342                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
343                         res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
344                         return res;
345                     }
346                 }
347                 else
348                 {
349                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is unowned.");
350                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownerthip transfer is required.");
351
352                     res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
353                     return res;
354                 }
355             }
356             else
357             {
358                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found");
359                 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
360                 return res;
361             }
362
363             if(cloudUuid.empty())
364             {
365                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
366                          "ACL provisioning is skipped due to empty UUID of cloud server");
367             }
368             else
369             {
370                 res = performACLProvisioningForCloudServer(ownedDevice, cloudUuid);
371                 if(res != ESResult::ES_OK)
372                 {
373                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performACLProvisioningForCloudServer");
374                     return res;
375                 }
376             }
377
378             if(credId < 1)
379             {
380                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
381                          "Cert. provisioning is skipped due to wrong cred ID (<1)");
382             }
383             else
384             {
385                 res = performCertProvisioningForCloudServer(ownedDevice, credId);
386                 if(res != ESResult::ES_OK)
387                 {
388                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performCertProvisioningForCloudServer");
389                     return res;
390                 }
391             }
392
393             return res;
394         }
395
396         ESResult EnrolleeSecurity::performCertProvisioningForCloudServer(
397             std::shared_ptr< OC::OCSecureResource > ownedDevice, int credId)
398         {
399             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performCertProvisioningForCloudServer IN");
400
401             ESResult res = ESResult::ES_CERT_PROVISIONING_FAILURE;
402
403             if(!ownedDevice)
404             {
405                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
406                 return res;
407             }
408
409             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Given CredId: %d", credId);
410
411             OC::ResultCallBack CertProvisioningCb = std::bind(
412                             &EnrolleeSecurity::CertProvisioningCb, this, std::placeholders::_1,
413                             std::placeholders::_2);
414             OCStackResult rst = ownedDevice->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
415                                                                     static_cast<uint16_t>(credId),
416                                                                     CertProvisioningCb);
417             if(OC_STACK_OK != rst)
418             {
419                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "provisionTrustCertChain error: %d", rst);
420                 return res;
421             }
422
423             std::unique_lock<std::mutex> lck(m_mtx);
424             m_cond.wait(lck);
425
426             if(certResult)
427             {
428                 res = ESResult::ES_OK;
429             }
430
431             return res;
432         }
433
434         ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(
435             std::shared_ptr< OC::OCSecureResource > ownedDevice, std::string& cloudUuid)
436         {
437             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performACLProvisioningForCloudServer IN");
438
439             ESResult res = ESResult::ES_ACL_PROVISIONING_FAILURE;
440
441             if(!ownedDevice)
442             {
443                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
444                 return res;
445             }
446
447             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Given cloudUuid: %s", cloudUuid.c_str());
448
449             OicUuid_t uuid;
450             if(OC_STACK_OK != ConvertStrToUuid(cloudUuid.c_str(), &uuid))
451             {
452                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
453                 return res;
454             }
455
456
457             // Create Acl for Cloud Server to be provisioned to Enrollee
458             OicSecAcl_t* acl = createAcl(uuid);
459             if(!acl)
460             {
461                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl error return");
462                 return res;
463             }
464
465             OC::ResultCallBack aclProvisioningCb = std::bind(
466                             &EnrolleeSecurity::ACLProvisioningCb, this, std::placeholders::_1,
467                             std::placeholders::_2);
468             // ACL provisioning to Enrollee
469             OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
470             if(OC_STACK_OK != rst)
471             {
472                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OCProvisionACL API error: %d", rst);
473                 return res;
474             }
475
476             std::unique_lock<std::mutex> lck(m_mtx);
477             m_cond.wait(lck);
478
479             if(aclResult)
480             {
481                 res = ESResult::ES_OK;
482             }
483
484             return res;
485         }
486
487         OicSecAcl_t* EnrolleeSecurity::createAcl(const OicUuid_t cloudUuid)
488         {
489             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl IN");
490
491             // allocate memory for |acl| struct
492             OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
493             if(!acl)
494             {
495                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
496                 return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
497             }
498             OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
499             if(!ace)
500             {
501                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,  "createAcl: OICCalloc error return");
502                 return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
503             }
504             LL_APPEND(acl->aces, ace);
505
506             memcpy(&ace->subjectuuid, &cloudUuid, UUID_LENGTH);
507
508             OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
509             if(!rsrc)
510             {
511                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
512                 OCDeleteACLList(acl);
513                 return NULL;
514             }
515
516             char href[] = "*";
517             size_t len = strlen(href)+1;  // '1' for null termination
518             rsrc->href = (char*) OICCalloc(len, sizeof(char));
519             if(!rsrc->href)
520             {
521                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,  "createAcl: OICCalloc error return");
522                 OCDeleteACLList(acl);
523                 return NULL;
524             }
525             OICStrcpy(rsrc->href, len, href);
526
527             size_t arrLen = 1;
528             rsrc->typeLen = arrLen;
529             rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
530             rsrc->interfaceLen = 1;
531             rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
532             rsrc->types[0] = OICStrdup("rt");   // ignore
533             rsrc->interfaces[0] = OICStrdup("if");  // ignore
534
535             LL_APPEND(ace->resources, rsrc);
536
537             ace->permission = 31;   // R/W/U/D
538
539             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl OUT");
540
541             return acl;
542         }
543
544         void EnrolleeSecurity::ACLProvisioningCb(PMResultList_t *result, int hasError)
545         {
546             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ACLProvisioningCb IN");
547
548             if (hasError)
549             {
550                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "ACL provisioning is failed with code (%d)", hasError);
551                aclResult = false;
552             }
553             else
554             {
555                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received ACL provisioning results: ");
556
557                std::string devUuid;
558                for (unsigned int i = 0; i < result->size(); i++)
559                {
560                    convertUUIDToString(result->at(i).deviceId.id, devUuid);
561                    OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d  for device %s",
562                                                            result->at(i).res, devUuid.c_str());
563                }
564                delete result;
565                aclResult = true;
566             }
567             m_cond.notify_all();
568         }
569
570         void EnrolleeSecurity::CertProvisioningCb(PMResultList_t *result, int hasError)
571         {
572             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "CertProvisioningCb IN");
573
574             if (hasError)
575             {
576                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Cert provisioning is failed with code (%d)", hasError);
577                certResult = false;
578             }
579             else
580             {
581                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received Cert. provisioning results: ");
582
583                std::string devUuid;
584                for (unsigned int i = 0; i < result->size(); i++)
585                {
586                    convertUUIDToString(result->at(i).deviceId.id, devUuid);
587                    OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d  for device %s",
588                                                            result->at(i).res, devUuid.c_str());
589                }
590                delete result;
591                certResult= true;
592             }
593             m_cond.notify_all();
594         }
595 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
596     }
597 }