replace : iotivity -> iotivity-sec
[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 #include "aclresource.h"
35 #include "internal/doxmresource.h"
36 #include "ocrandom.h"
37
38 namespace OIC
39 {
40     namespace Service
41     {
42         namespace
43         {
44             static const char COAP[] = "coap://";
45             static const char COAPS[] = "coaps://";
46             static const char COAP_TCP[] = "coap+tcp://";
47             static const char COAP_GATT[] = "coap+gatt://";
48             static const char COAP_RFCOMM[] = "coap+rfcomm://";
49         }
50
51         #define MAX_PERMISSION_LENGTH (5)
52         #define CREATE (1)
53         #define READ (2)
54         #define UPDATE (4)
55         #define DELETE (8)
56         #define NOTIFY (16)
57         #define DASH '-'
58
59         // TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
60         // The value should be accepted from the application as a parameter during ocplatform
61         // config call
62
63 #ifdef __APPLE__
64         #define ES_SEC_DISCOVERY_TIMEOUT 15
65 #else
66         #define ES_SEC_DISCOVERY_TIMEOUT 5
67 #endif
68
69         EnrolleeSecurity::EnrolleeSecurity(std::shared_ptr< OC::OCResource > resource)
70         {
71             m_ocResource = resource;
72         }
73
74         void EnrolleeSecurity::onEnrolleeSecuritySafetyCB(OC::PMResultList_t *result,
75                                                         int hasError,
76                                                         ESSecurityCb cb,
77                                                         std::weak_ptr<EnrolleeSecurity> this_ptr)
78         {
79             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "onEnrolleeSecuritySafetyCB");
80             std::shared_ptr<EnrolleeSecurity> Ptr = this_ptr.lock();
81             if(Ptr)
82             {
83                 cb(result, hasError);
84             }
85         }
86
87         void EnrolleeSecurity::convertUUIDToString(const uint8_t uuid[UUID_SIZE],
88                                                               std::string& uuidString)
89         {
90             char uuidArray[UUID_STRING_SIZE] = {'\0',};
91             int ret = snprintf(uuidArray, UUID_STRING_SIZE,
92                     "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
93                     uuid[0], uuid[1], uuid[2], uuid[3],
94                     uuid[4], uuid[5], uuid[6], uuid[7],
95                     uuid[8], uuid[9], uuid[10], uuid[11],
96                     uuid[12], uuid[13], uuid[14], uuid[15]
97                     );
98
99             if (ret != UUID_STRING_SIZE - 1)
100             {
101                 return;
102             }
103
104             uuidString = uuidArray;
105         }
106
107         std::string EnrolleeSecurity::getResourceDeviceAddress(const std::string& host)
108         {
109             size_t prefix_len = 0;
110
111             if (host.compare(0, sizeof(COAP) - 1, COAP) == 0)
112             {
113                 prefix_len = sizeof(COAP) - 1;
114             }
115             else if (host.compare(0, sizeof(COAPS) - 1, COAPS) == 0)
116             {
117                 prefix_len = sizeof(COAPS) - 1;
118             }
119             else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
120             {
121                 prefix_len = sizeof(COAP_TCP) - 1;
122             }
123             else if (host.compare(0, sizeof(COAP_GATT) - 1, COAP_GATT) == 0)
124             {
125                 prefix_len = sizeof(COAP_GATT) - 1;
126             }
127             else if (host.compare(0, sizeof(COAP_RFCOMM) - 1, COAP_RFCOMM) == 0)
128             {
129                 prefix_len = sizeof(COAP_RFCOMM) - 1;
130             }
131             else
132             {
133                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
134                     "Well-known prefix for connectivity is not found. Please check OCResource::setHost");
135                 return {};
136             }
137
138             // remove prefix
139             std::string host_token = host.substr(prefix_len);
140
141             if (host_token[0] == '[') // IPv6
142             {
143                 size_t bracket = host_token.find(']');
144
145                 // extract the ipv6 address
146                 return host_token.substr(0, bracket + 1);
147             }
148             else
149             {
150                 size_t dot = host_token.find('.');
151                 if (std::string::npos == dot) // MAC
152                 {
153                     size_t semi_count = std::count(host_token.begin(), host_token.end(), ':');
154                     if (semi_count > 5)
155                     {
156                         size_t found_semi = host_token.find_last_of(':');
157                         host_token = host_token.substr(0, found_semi);
158                     }
159                     return host_token;
160                 }
161                 else // IPv4
162                 {
163                     size_t colon = host_token.find(':');
164
165                     // extract the ipv4 address
166                     return host_token.substr(0, colon);
167                 }
168             }
169         }
170
171         bool EnrolleeSecurity::isOwnerIDMatched(std::shared_ptr< OC::OCSecureResource > foundDevice)
172         {
173             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isOwnerIDMatched IN");
174
175             if(foundDevice.get() == nullptr)
176             {
177                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "foundDevice is NULL ptr");
178                 return false;
179             }
180
181             bool ret = false;
182             std::string ownerID;
183             char uuidString[UUID_STRING_SIZE] = {};
184             if(RAND_UUID_OK == OCConvertUuidToString(foundDevice->getDevPtr()->doxm->owner.id, uuidString))
185             {
186                 ownerID = uuidString;
187             }
188             else
189             {
190                 ownerID = {};
191             }
192
193             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Mediator ID %s", m_mediatorID.c_str());
194             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Enrollee's Owner ID %s", ownerID.c_str());
195
196             if(ownerID == m_mediatorID)
197             {
198                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
199                     "The found device's first owner ID is matched with Mediator's ID");
200                 ret = true;
201             }
202             else
203             {
204                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
205                     "The found device's first owner ID is NOT matched with Mediator's ID");
206             }
207
208             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isOwnerIDMatched OUT");
209
210             return ret;
211         }
212
213 #ifdef MULTIPLE_OWNER
214         bool EnrolleeSecurity::isSubOwnerIDMatched(std::shared_ptr< OC::OCSecureResource > foundDevice)
215         {
216             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isSubOwnerIDMatched IN");
217
218             if(foundDevice.get() == nullptr)
219             {
220                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
221                     "The found device's sub owner ID is NOT matched with Mediator's ID");
222
223                 return false;
224             }
225
226             bool ret = false;
227             std::string subOwnerID;
228             char uuidString[UUID_STRING_SIZE] = {};
229
230             OicSecSubOwner_t* subOwnerList = foundDevice->getDevPtr()->doxm->subOwners;
231
232             while(subOwnerList)
233             {
234                 if(RAND_UUID_OK == OCConvertUuidToString(subOwnerList->uuid.id, uuidString))
235                 {
236                     subOwnerID = uuidString;
237                 }
238                 else
239                 {
240                     subOwnerID = {};
241                 }
242
243                 if(subOwnerID == m_mediatorID)
244                 {
245                     OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
246                     "The found device's owner ID is matched with Mediator's ID as a second owner");
247                     ret = true;
248                     break;
249                 }
250                 subOwnerList = subOwnerList->next;
251             }
252
253             if(!ret)
254             {
255                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
256                     "The found device's sub owner ID is NOT matched with Mediator's ID");
257             }
258
259             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isSubOwnerIDMatched OUT");
260             return ret;
261         }
262
263         void EnrolleeSecurity::changeMOTMethodCB(PMResultList_t *result, int hasError)
264         {
265             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "changeMOTMethodCB IN");
266             if (hasError)
267             {
268                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
269                                 "requestEnableMOTMode API is failed with error %d", hasError);
270                 enableMOTModeResult = false;
271             }
272             else
273             {
274                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestEnableMOTMode API is succeeded");
275                 enableMOTModeResult = true;
276             }
277
278             delete result;
279             m_cond.notify_all();
280         }
281
282
283         void EnrolleeSecurity::selectMOTMethodCB(PMResultList_t *result, int hasError)
284         {
285             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethodCB IN");
286             if (hasError)
287             {
288                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
289                                 "selectMOTMethod API is failed with error %d", hasError);
290                 motMethodProvResult = false;
291             }
292             else
293             {
294                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethod API is succeeded");
295                 motMethodProvResult = true;
296             }
297
298             delete result;
299             m_cond.notify_all();
300         }
301
302         void EnrolleeSecurity::preconfigPinProvCB(PMResultList_t *result, int hasError)
303         {
304             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "preconfigPinProvCB IN");
305             if (hasError)
306             {
307                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
308                                 "provisionPreconfPin API is failed with error %d", hasError);
309                 preConfigPinProvResult = false;
310             }
311             else
312             {
313                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionPreconfPin API is succeeded");
314                 preConfigPinProvResult = true;
315             }
316
317             delete result;
318             m_cond.notify_all();
319         }
320
321         void EnrolleeSecurity::multipleOwnershipTransferCb(OC::PMResultList_t *result, int hasError)
322         {
323             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "multipleOwnershipTransferCb IN");
324
325             otmResult = false;
326
327             if (hasError)
328             {
329                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "multipleOwnershipTransferCb is failed with code(%d)", hasError);
330                 otmResult = false;
331                 m_cond.notify_all();
332             }
333             else
334             {
335                 for (unsigned int i = 0; i < result->size(); i++)
336                 {
337                     std::string uuid;
338                     convertUUIDToString(result->at(i).deviceId.id, uuid);
339
340                     if(m_ocResource != NULL && m_ocResource->sid() == uuid)
341                     {
342                         if( OC_STACK_OK == result->at(i).res )
343                         {
344                             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "multipleOwnershipTransferCb is succeeded");
345                             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
346                             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", uuid.c_str());
347
348                             otmResult = true;
349                         }
350                         else
351                         {
352                             OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "multipleOwnershipTransfer is failed with code(%d)", hasError);
353                             otmResult = false;
354                         }
355                     }
356                 }
357                 delete result;
358                 m_cond.notify_all();
359             }
360         }
361
362         ESResult EnrolleeSecurity::requestSetPreconfPinData(const ESOwnershipTransferData& MOTData)
363         {
364             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestSetPreconfPinData IN");
365
366             ESResult res = ESResult::ES_ERROR;
367
368             OC::ResultCallBack preconfigPinProvCB = std::bind(
369                     &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
370                     std::placeholders::_1, std::placeholders::_2,
371                     static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::preconfigPinProvCB,
372                     this, std::placeholders::_1, std::placeholders::_2)),
373                     shared_from_this());
374
375             std::string pin = MOTData.getPreConfiguredPin();
376
377             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionPreconfPin is called.");
378             if(OC_STACK_OK != m_securedResource->provisionPreconfPin(
379                                     pin.c_str(), pin.length(), preconfigPinProvCB))
380             {
381                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionPreconfPin API error");
382                 res = ESResult:: ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE;
383                 return res;
384             }
385
386             std::unique_lock<std::mutex> lck(m_mtx);
387             m_cond.wait(lck);
388
389             if(!preConfigPinProvResult)
390             {
391                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionPreconfPin is failed.");
392                 res = ESResult:: ES_PRE_CONFIG_PIN_PROVISIONING_FAILURE;
393                 return res;
394             }
395
396             return ESResult::ES_OK;
397         }
398
399         ESResult EnrolleeSecurity::requestSetMOTMethod(const ESOwnershipTransferData& MOTData)
400         {
401             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestSetMOTMethod IN");
402
403             ESResult res = ESResult::ES_ERROR;
404
405             OC::ResultCallBack selectMOTMethodCB = std::bind(
406                     &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
407                     std::placeholders::_1, std::placeholders::_2,
408                     static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::selectMOTMethodCB,
409                     this, std::placeholders::_1, std::placeholders::_2)),
410                     shared_from_this());
411
412             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "selectMOTMethod is called.");
413             if(OC_STACK_OK != m_securedResource->selectMOTMethod(
414                                     MOTData.getMOTMethod(),
415                                     selectMOTMethodCB))
416             {
417                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "selectMOTMethod API error");
418                 res = ESResult:: ES_MOT_METHOD_SELECTION_FAILURE;
419                 return res;
420             }
421
422             std::unique_lock<std::mutex> lck(m_mtx);
423             m_cond.wait(lck);
424
425             if(!motMethodProvResult)
426             {
427                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "selectMOTMethod is failed.");
428                 res = ESResult:: ES_MOT_METHOD_SELECTION_FAILURE;
429                 return res;
430             }
431
432             return ESResult::ES_OK;
433         }
434
435         ESResult EnrolleeSecurity::requestEnableMOTMode()
436         {
437             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "requestEnableMOTMode IN");
438             ESResult res = ESResult:: ES_ERROR;
439
440             OC::ResultCallBack changeMOTMethodCB = std::bind(
441                     &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
442                     std::placeholders::_1, std::placeholders::_2,
443                     static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::changeMOTMethodCB,
444                     this, std::placeholders::_1, std::placeholders::_2)),
445                     shared_from_this());
446
447             if(OC_STACK_OK !=
448                 m_securedResource->changeMOTMode(OIC_MULTIPLE_OWNER_ENABLE, changeMOTMethodCB))
449             {
450                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "changeMOTMode is failed.");
451                 return ESResult:: ES_MOT_ENABLING_FAILURE;
452             }
453
454             std::unique_lock<std::mutex> lck(m_mtx);
455             m_cond.wait(lck);
456
457             if(!enableMOTModeResult)
458             {
459                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "requestEnableMOTMode is failed.");
460                 res = ESResult:: ES_MOT_ENABLING_FAILURE;
461                 return res;
462             }
463
464             return ESResult::ES_OK;
465         }
466
467         ESResult EnrolleeSecurity::provisionMOTConfig(const ESOwnershipTransferData& MOTData)
468         {
469             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionMOTConfig IN");
470             ESResult res = ESResult:: ES_ERROR;
471
472             if(!m_securedResource->isMOTEnabled())
473             {
474                 res = requestEnableMOTMode();
475                 if(res != ESResult::ES_OK)
476                 {
477                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "requestEnableMOTMode is failed.");
478                     return res;
479                 }
480             }
481
482             if( OIC_PRECONFIG_PIN == MOTData.getMOTMethod() &&
483                 !MOTData.getPreConfiguredPin().empty())
484             {
485                 res = requestSetPreconfPinData(MOTData);
486
487                 if(res != ESResult::ES_OK)
488                 {
489                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "RequestSetPreconfPinData is failed.");
490                     return res;
491                 }
492             }
493             if(OIC_PRECONFIG_PIN == MOTData.getMOTMethod() ||
494                OIC_RANDOM_DEVICE_PIN == MOTData.getMOTMethod())
495             {
496                 res = requestSetMOTMethod(MOTData);
497
498                 if(res != ESResult::ES_OK)
499                 {
500                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "RequestSetMOTMethod is failed.");
501                     return res;
502                 }
503             }
504             return res;
505         }
506 #endif
507
508         void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError
509                                                    , ESResult& res)
510         {
511             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb IN");
512
513             otmResult = false;
514
515             if (hasError)
516             {
517                 for (unsigned int i = 0; i < result->size(); i++)
518                 {
519                     std::string uuid;
520                     convertUUIDToString(result->at(i).deviceId.id, uuid);
521
522                     if(m_ocResource != NULL && m_ocResource->sid() == uuid)
523                     {
524                         if(OC_STACK_USER_DENIED_REQ == result->at(i).res)
525                         {
526                             res = ESResult::ES_USER_DENIED_CONFIRMATION_REQ;
527                         }
528                         else if(OC_STACK_AUTHENTICATION_FAILURE  == result->at(i).res)
529                         {
530                             OicSecOxm_t oxm = OIC_OXM_COUNT;
531                             if(OC_STACK_OK != m_securedResource->getOTMethod(&oxm))
532                             {
533                                 otmResult = false;
534                                 return;
535                             }
536
537                             if(OIC_MANUFACTURER_CERTIFICATE == oxm)
538                             {
539                                 res = ESResult::ES_AUTHENTICATION_FAILURE_WITH_WRONG_CERT;
540                             }
541                             else if(OIC_CON_MFG_CERT == oxm)
542                             {
543                                 res = ESResult::ES_AUTHENTICATION_FAILURE_WITH_WRONG_CERT;
544                             }
545                             else if(OIC_RANDOM_DEVICE_PIN == oxm)
546                             {
547                                 res = ESResult::ES_AUTHENTICATION_FAILURE_WITH_WRONG_PIN;
548                             }
549                         }
550                         else if(OC_STACK_COMM_ERROR == result->at(i).res)
551                         {
552                             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
553                                 "OwnershipTransfer is failed with OC_STACK_COMM_ERROR");
554                             res = ESResult::ES_COMMUNICATION_ERROR;
555                         }
556                         else if(OC_STACK_TIMEOUT == result->at(i).res)
557                         {
558                             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
559                                 "OwnershipTransfer is failed with OC_STACK_TIMEOUT");
560                             res = ESResult::ES_COMMUNICATION_ERROR;
561                         }
562                         else if(OC_STACK_GATEWAY_TIMEOUT== result->at(i).res)
563                         {
564                             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
565                                 "OwnershipTransfer is failed with OC_STACK_GATEWAY_TIMEOUT");
566                             res = ESResult::ES_COMMUNICATION_ERROR;
567                         }
568                     }
569                 }
570                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransfer is failed with ESResult(%d)", res);
571
572                 otmResult = false;
573             }
574             else
575             {
576                 for (unsigned int i = 0; i < result->size(); i++)
577                 {
578                     std::string uuid;
579                     convertUUIDToString(result->at(i).deviceId.id, uuid);
580
581                     if(m_ocResource != NULL && m_ocResource->sid() == uuid)
582                     {
583                         if( OC_STACK_OK == result->at(i).res )
584                         {
585                             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "OwnershipTransfer is succeeded");
586                             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
587                             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", uuid.c_str());
588
589                             otmResult = true;
590                         }
591                         else
592                         {
593                             OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransfer is failed with code(%d)", hasError);
594                             otmResult = false;
595                         }
596                     }
597                 }
598             }
599
600             delete result;
601             m_cond.notify_all();
602         }
603
604         ESResult EnrolleeSecurity::discoverTargetSecureResource()
605         {
606             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "discoverTargetSecureResource IN");
607
608             OCStackResult result = OC_STACK_ERROR;
609
610             OicUuid_t uuid;
611             if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
612             {
613                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
614                 return ES_ERROR;
615             }
616
617             // If a discovered resource uses BLE transport, unicast for secure resource discovery is
618             // used.
619             if( m_ocResource->connectivityType() & CT_ADAPTER_GATT_BTLE )
620             {
621                 std::string GattAddress = getResourceDeviceAddress(m_ocResource->host());
622                 if(!GattAddress.empty())
623                 {
624                     result = OCSecure::discoverSingleDeviceInUnicast(ES_SEC_DISCOVERY_TIMEOUT,
625                                                             &uuid,
626                                                             GattAddress,
627                                                             m_ocResource->connectivityType(),
628                                                             m_securedResource);
629                     if(result != OC_STACK_OK)
630                     {
631                         return ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
632                     }
633                 }
634                 else
635                 {
636                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "GATT BTLE address format is wrong.");
637                     return ES_ERROR;
638                 }
639             }
640             else
641             {
642                 result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
643                                                         &uuid,
644                                                         m_securedResource);
645                 if(result != OC_STACK_OK)
646                 {
647                     return ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
648                 }
649             }
650
651             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
652             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", m_securedResource->getDevAddr().c_str());
653             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "SID: %s", m_securedResource->getDeviceID().c_str());
654             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", m_securedResource->getOwnedStatus());
655
656             OicSecOxm_t selectedOTMethod = OIC_OXM_COUNT;
657             if( OC_STACK_OK != m_securedResource->getOTMethod(&selectedOTMethod) )
658             {
659                 selectedOTMethod = OIC_OXM_COUNT; // Out-of-range
660             }
661             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Selected OT Method: %d", (int)(selectedOTMethod));
662 #ifdef MULTIPLE_OWNER
663             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "MOT Supported: %d", (int)(m_securedResource->isMOTSupported()));
664             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "MOT Enabled: %d", (int)(m_securedResource->isMOTEnabled()));
665 #endif
666             if(m_securedResource->getOwnedStatus())
667             {
668                 char uuidString[UUID_STRING_SIZE] = {};
669                 if(RAND_UUID_OK == OCConvertUuidToString(m_securedResource->getDevPtr()->doxm->owner.id, uuidString))
670                 {
671                     OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Owner ID: %s", uuidString);
672                 }
673                 else
674                 {
675                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OCConvertUuidToString is failed");
676                 }
677             }
678
679             return ES_OK;
680         }
681
682         ESOwnershipTransferData EnrolleeSecurity::getOwnershipTransferDataFromUser
683                                             (SecurityProvStatusCbWithOption callback)
684         {
685             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "getOwnershipTransferDataFromUser IN");
686             ESOwnershipTransferData ownershipTransferData;
687
688             std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
689                              std::make_shared< SecProvisioningStatus >
690                                            (m_securedResource,
691                                            ESResult::ES_SECURE_RESOURCE_IS_DISCOVERED);
692             ownershipTransferData = callback(securityProvisioningStatus);
693 #ifdef MULTIPLE_OWNER
694             if(OIC_RANDOM_DEVICE_PIN == ownershipTransferData.getMOTMethod())
695             {
696                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Selected MOT Method: OIC_RANDOM_DEVICE_PIN");
697             }
698             else if(OIC_PRECONFIG_PIN == ownershipTransferData.getMOTMethod())
699             {
700                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Selected MOT Method: OIC_PRECONFIG_PIN");
701                 OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Pre-configured PIN: %s",
702                                     ownershipTransferData.getPreConfiguredPin().c_str());
703             }
704 #endif
705             return ownershipTransferData;
706         }
707
708         ESResult EnrolleeSecurity::syncUpWithMediatorDB()
709         {
710             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "syncUpWithMediatorDB IN");
711
712             OCStackResult result = OC_STACK_ERROR;
713             ESResult res = ESResult::ES_ERROR;
714
715             OC::ResultCallBack removeDeviceWithUuidCB = std::bind(
716                     &EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
717                     std::placeholders::_1, std::placeholders::_2,
718                     static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::removeDeviceWithUuidCB,
719                     this, std::placeholders::_1, std::placeholders::_2)),
720                     shared_from_this());
721
722             result = OCSecure::removeDeviceWithUuid(ES_SEC_DISCOVERY_TIMEOUT,
723                                                     m_ocResource->sid(),
724                                                     removeDeviceWithUuidCB);
725             if(result != OC_STACK_OK)
726             {
727                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid failed. (%d)", result);
728                 res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
729                 return res;
730             }
731
732             std::unique_lock<std::mutex> lck(m_mtx);
733             m_cond.wait_for(lck, std::chrono::seconds(ES_SEC_DISCOVERY_TIMEOUT));
734
735             if(!removeDeviceResult)
736             {
737                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Removing device is failed.");
738                 res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
739                 return res;
740             }
741             return ESResult::ES_OK;
742         }
743
744         std::string EnrolleeSecurity::getMediatorDevID()
745         {
746             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "getMediatorDevID IN");
747             OCUUIdentity* mediatorDevId = (OCUUIdentity* )OICMalloc(sizeof(OCUUIdentity));
748             if(!mediatorDevId)
749             {
750                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionOwnership: OICMalloc error return");
751                 return {};
752             }
753
754             if(OC::OCPlatform::getDeviceId(mediatorDevId) != OC_STACK_OK)
755             {
756                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "getDeviceId is failed.");
757                 OICFree(mediatorDevId);
758                 return {};
759             }
760
761             char uuidString[UUID_STRING_SIZE] = {};
762             if(RAND_UUID_OK == OCConvertUuidToString(mediatorDevId->id, uuidString))
763             {
764                 OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Mediator UUID : %s", uuidString);
765                 OICFree(mediatorDevId);
766                 return std::string(uuidString);
767             }
768
769             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OCConvertUuidToString is failed.");
770             OICFree(mediatorDevId);
771             return {};
772         }
773
774         ESResult EnrolleeSecurity::provisionOwnership(SecurityProvStatusCbWithOption callback)
775         {
776             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionOwnership IN");
777
778             ESResult res = ESResult:: ES_ERROR;
779
780             ESOwnershipTransferData ownershipTransferData;
781
782             std::string mediatorDevIdStr = getMediatorDevID();
783             if(mediatorDevIdStr.empty())
784             {
785                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "getMediatorDevID is failed.");
786                 return res;
787             }
788             else
789             {
790                 m_mediatorID = mediatorDevIdStr;
791             }
792
793             res = discoverTargetSecureResource();
794
795             if (res != ES_OK)
796             {
797                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Secure Resource Discovery failed.");
798                 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
799                 return res;
800             }
801             else if (m_securedResource)
802             {
803                 if(callback != NULL)
804                 {
805                     ownershipTransferData = getOwnershipTransferDataFromUser(callback);
806                 }
807
808                 if(m_securedResource->getOwnedStatus())
809                 {
810                     if(isOwnedDeviceRegisteredInDB())
811                     {
812 #ifdef MULTIPLE_OWNER
813                         if(isSubOwnerIDMatched(m_securedResource))
814                         {
815                             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
816                                 "The found device is already owned by Mediator.(SUCCESS)");
817                             res = ESResult::ES_OK;
818                             return res;
819                         }
820
821                         if(isOwnerIDMatched(m_securedResource))
822                         {
823                             if((OIC_PRECONFIG_PIN == ownershipTransferData.getMOTMethod() ||
824                                 OIC_RANDOM_DEVICE_PIN == ownershipTransferData.getMOTMethod()))
825                             {
826                                 if(m_securedResource->isMOTSupported())
827                                 {
828                                     res = provisionMOTConfig(ownershipTransferData);
829                                     if(res != ES_OK)
830                                     {
831                                         OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
832                                             "provisionMOTConfig is failed.");
833                                         return res;
834                                     }
835                                     OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
836                                         "The found device is already owned by Mediator and enabled MOT mode.");
837                                     return res;
838                                 }
839                                 else
840                                 {
841                                     OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
842                                         "The found device is not supported MOT");
843                                     return ESResult:: ES_MOT_NOT_SUPPORTED;
844                                 }
845                             }
846                             else
847                             {
848                                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
849                                     "The found device is already owned by Mediator.(SUCCESS)");
850                                 res = ESResult::ES_OK;
851                                 return res;
852                             }
853                         }
854
855                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
856                             "An ownership transfer knowledge is not synchronized"
857                             "between mediator and found enrollee.(FAILED)");
858                         res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
859                         return res;
860 #else
861                         if(isOwnerIDMatched(m_securedResource))
862                         {
863                             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
864                                 "The found device is already owned by Mediator.(SUCCESS)");
865                             res = ESResult::ES_OK;
866                             return res;
867                         }
868                         else
869                         {
870                             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
871                                 "An ownership transfer knowledge is not synchronized"
872                                 "between mediator and found enrollee.(FAILED)");
873                             res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
874                             return res;
875                         }
876 #endif
877                     }
878 #ifdef MULTIPLE_OWNER
879                     else if( !isOwnedDeviceRegisteredInDB() &&
880                              !isOwnerIDMatched(m_securedResource) &&
881                              !isSubOwnerIDMatched(m_securedResource) &&
882                              m_securedResource->isMOTEnabled() &&
883                              (OIC_PRECONFIG_PIN == ownershipTransferData.getMOTMethod() ||
884                               OIC_RANDOM_DEVICE_PIN == ownershipTransferData.getMOTMethod()))
885                     {
886                         // MOT case;
887                         res = performMultipleOwnershipTransfer(ownershipTransferData);
888
889                         if(res != ESResult::ES_OK)
890                         {
891                             OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
892                                             "Multiple Ownership-Transfer failed. (%d)", res);
893                             return res;
894                         }
895                     }
896                     else if( !isOwnedDeviceRegisteredInDB() &&
897                              (isOwnerIDMatched(m_securedResource) ||
898                              isSubOwnerIDMatched(m_securedResource)))
899 #else
900                     else if( !isOwnedDeviceRegisteredInDB() && isOwnerIDMatched(m_securedResource))
901 #endif
902                     {
903                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
904                         "An ownership transfer knowledge is not synchronized between mediator and found enrollee.(FAILED)");
905                         res = ESResult::ES_OWNERSHIP_IS_NOT_SYNCHRONIZED;
906                         return res;
907                     }
908                     else
909                     {
910                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
911                             "The found device is already owned by Other Mediator.(FAILED)");
912                         res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
913                         return res;
914                     }
915                 }
916                 else
917                 {
918                     if(isOwnedDeviceRegisteredInDB())
919                     {
920                         res = syncUpWithMediatorDB();
921
922                         if(res != ESResult::ES_OK)
923                         {
924                             OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG,
925                                             "syncUpWithMediatorDB failed. (%d)", res);
926                             return res;
927                         }
928                         OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Removing device is succeeded.");
929                     }
930                     res = performOwnershipTransfer();
931
932                     if(res != ESResult::ES_OK)
933                     {
934                         OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed. (%d)", res);
935                         return res;
936                     }
937 #ifdef MULTIPLE_OWNER
938                     if( m_securedResource->isMOTSupported() &&
939                         ownershipTransferData.getMOTMethod() != OIC_OXM_COUNT)
940                     {
941                         res = provisionMOTConfig(ownershipTransferData);
942                     }
943                     return res;
944 #endif
945                 }
946             }
947             else
948             {
949                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found.");
950                 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
951             }
952             return res;
953         }
954
955         ESResult EnrolleeSecurity::performOwnershipTransfer()
956         {
957             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performOwnershipTransfer IN.");
958
959             OCStackResult result = OC_STACK_ERROR;
960             ESResult res = ESResult::ES_ERROR;
961
962             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
963                     m_securedResource->getDeviceID().c_str());
964
965             OC::ResultCallBack ownershipTransferCb =
966                 std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
967                           std::placeholders::_1, std::placeholders::_2,
968                           static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::ownershipTransferCb,
969                           this, std::placeholders::_1, std::placeholders::_2, std::ref(res))),
970                           shared_from_this());
971
972
973             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is excuted");
974             result = m_securedResource->doOwnershipTransfer(ownershipTransferCb);
975
976             if (result != OC_STACK_OK)
977             {
978                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is failed");
979                 return ESResult::ES_ERROR;
980             }
981
982             std::unique_lock<std::mutex> lck(m_mtx);
983             m_cond.wait(lck);
984
985             if(!otmResult)
986             {
987                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
988                 return res;
989             }
990
991             return ESResult::ES_OK;
992         }
993
994 #ifdef MULTIPLE_OWNER
995         ESResult EnrolleeSecurity::performMultipleOwnershipTransfer(const ESOwnershipTransferData& MOTdata)
996         {
997             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performMultipleOwnershipTransfer IN.");
998
999             OCStackResult result = OC_STACK_ERROR;
1000
1001             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Transfering sub-ownership for : %s ",
1002                     m_securedResource->getDeviceID().c_str());
1003
1004             if(OIC_PRECONFIG_PIN == MOTdata.getMOTMethod() &&
1005                !MOTdata.getPreConfiguredPin().empty())
1006             {
1007                 std::string pin = MOTdata.getPreConfiguredPin();
1008
1009                 result = m_securedResource->addPreconfigPIN(pin.c_str(), pin.length());
1010                 if(OC_STACK_OK != result)
1011                 {
1012                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "addPreconfigPIN is failed");
1013                     return ESResult::ES_ERROR;
1014                 }
1015
1016                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Preconfig PIN : %s", pin.c_str());
1017             }
1018
1019             OC::ResultCallBack multipleOwnershipTransferCb =
1020                 std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
1021                           std::placeholders::_1, std::placeholders::_2,
1022                           static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::multipleOwnershipTransferCb,
1023                           this, std::placeholders::_1, std::placeholders::_2)),
1024                           shared_from_this());
1025
1026             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "doMultipleOwnershipTransfer is excuted");
1027
1028             result = m_securedResource->doMultipleOwnershipTransfer(multipleOwnershipTransferCb);
1029             if(OC_STACK_OK != result)
1030             {
1031                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doMultipleOwnershipTransfer is failed");
1032                 return ESResult::ES_ERROR;
1033             }
1034
1035             std::unique_lock<std::mutex> lck(m_mtx);
1036             m_cond.wait(lck);
1037
1038             if(!otmResult)
1039             {
1040                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Multiple Ownership-Transfer failed.");
1041                 return ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
1042             }
1043
1044             return ESResult::ES_OK;
1045         }
1046 #endif
1047
1048         void EnrolleeSecurity::removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError)
1049         {
1050             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuidCB IN");
1051
1052             if (hasError)
1053             {
1054                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is failed with code (%d)", hasError);
1055                removeDeviceResult = false;
1056             }
1057
1058             else
1059             {
1060                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is succeeded");
1061
1062                for (unsigned int i = 0; i < result->size(); i++)
1063                {
1064                     std::string uuid;
1065                     convertUUIDToString(result->at(i).deviceId.id, uuid);
1066
1067                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
1068                     OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", uuid.c_str());
1069                }
1070                removeDeviceResult = true;
1071             }
1072             m_cond.notify_all();
1073         }
1074
1075         bool EnrolleeSecurity::isOwnedDeviceRegisteredInDB()
1076         {
1077             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "isOwnedDeviceRegisteredInDB IN");
1078
1079             OCStackResult res = OC_STACK_ERROR;
1080
1081             OCUuidList_t *uuidList = NULL;
1082             size_t numOfDevices = 0;
1083
1084             res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
1085             if (OC_STACK_OK != res)
1086             {
1087                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while getting info from DB");
1088                 OICFree(uuidList);
1089                 return false;
1090             }
1091
1092             OCUuidList_t *pUuidList = uuidList;
1093             while (pUuidList)
1094             {
1095                 std::string uuid;
1096                 convertUUIDToString(pUuidList->dev.id, uuid);
1097                 OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG,
1098                     "m_ocResource->sid(): %s, cur DB UUID %s",
1099                     m_ocResource->sid().c_str(), uuid.c_str());
1100                 if(m_ocResource->sid() == uuid.c_str())
1101                 {
1102                     OICFree(uuidList);
1103                     return true;
1104                 }
1105                 pUuidList = pUuidList->next;
1106             }
1107             OICFree(uuidList);
1108             return false;
1109         }
1110
1111
1112         std::string EnrolleeSecurity::getUUID() const
1113         {
1114             return m_ocResource->sid();
1115         };
1116
1117 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
1118         ESResult EnrolleeSecurity::provisionSecurityForCloudServer(
1119             std::string cloudUuid, int credId)
1120         {
1121             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionSecurityForCloudServer IN");
1122
1123             ESResult res = ESResult::ES_ERROR;
1124
1125             // Need to discover Owned device in a given network, again
1126             std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
1127
1128             OCStackResult result = OC_STACK_ERROR;
1129             OicUuid_t uuid;
1130             if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
1131             {
1132                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
1133                 return res;
1134             }
1135
1136             // If a discovered resource uses BLE transport, unicast for secure resource discovery is
1137             // used.
1138             if( m_ocResource->connectivityType() & CT_ADAPTER_GATT_BTLE )
1139             {
1140                 std::string GattAddress = getResourceDeviceAddress(m_ocResource->host());
1141                 if(!GattAddress.empty())
1142                 {
1143                     result = OCSecure::discoverSingleDeviceInUnicast(ES_SEC_DISCOVERY_TIMEOUT,
1144                                                             &uuid,
1145                                                             GattAddress,
1146                                                             m_ocResource->connectivityType(),
1147                                                             ownedDevice);
1148                 }
1149                 else
1150                 {
1151                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "GATT BTLE address format is wrong.");
1152                     res = ESResult:: ES_ERROR;
1153                     return res;
1154                 }
1155             }
1156             else
1157             {
1158                 result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
1159                                                         &uuid,
1160                                                         ownedDevice);
1161             }
1162
1163             if (result != OC_STACK_OK)
1164             {
1165                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "secureResource Discovery failed.");
1166                 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
1167                 return res;
1168             }
1169             else if (ownedDevice)
1170             {
1171                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
1172                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", ownedDevice->getDevAddr().c_str());
1173                 OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "SID: %s", ownedDevice->getDeviceID().c_str());
1174                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", ownedDevice->getOwnedStatus());
1175
1176                 if (ownedDevice->getOwnedStatus())
1177                 {
1178                     if(!isOwnedDeviceRegisteredInDB())
1179                     {
1180                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
1181                         res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
1182                         return res;
1183                     }
1184                 }
1185                 else
1186                 {
1187                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is unowned.");
1188                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownerthip transfer is required.");
1189
1190                     res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
1191                     return res;
1192                 }
1193             }
1194             else
1195             {
1196                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found");
1197                 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
1198                 return res;
1199             }
1200
1201             if(cloudUuid.empty())
1202             {
1203                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
1204                          "ACL provisioning is skipped due to empty UUID of cloud server");
1205             }
1206             else
1207             {
1208                 res = performACLProvisioningForCloudServer(ownedDevice, cloudUuid);
1209                 if(res != ESResult::ES_OK)
1210                 {
1211                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performACLProvisioningForCloudServer");
1212                     return res;
1213                 }
1214             }
1215
1216             if(credId < 1)
1217             {
1218                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
1219                          "Cert. provisioning is skipped due to wrong cred ID (<1)");
1220             }
1221             else
1222             {
1223                 res = performCertProvisioningForCloudServer(ownedDevice, credId);
1224                 if(res != ESResult::ES_OK)
1225                 {
1226                     OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performCertProvisioningForCloudServer");
1227                     return res;
1228                 }
1229             }
1230
1231             return res;
1232         }
1233
1234         ESResult EnrolleeSecurity::performCertProvisioningForCloudServer(
1235             std::shared_ptr< OC::OCSecureResource > ownedDevice, int credId)
1236         {
1237             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performCertProvisioningForCloudServer IN");
1238
1239             ESResult res = ESResult::ES_CERT_PROVISIONING_FAILURE;
1240
1241             if(!ownedDevice)
1242             {
1243                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
1244                 return res;
1245             }
1246
1247             OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Given CredId: %d", credId);
1248
1249             OC::ResultCallBack CertProvisioningCb =
1250                 std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
1251                           std::placeholders::_1, std::placeholders::_2,
1252                           static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::certProvisioningCb,
1253                           this, std::placeholders::_1, std::placeholders::_2)),
1254                           shared_from_this());
1255
1256             OCStackResult rst = ownedDevice->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
1257                                                                     static_cast<uint16_t>(credId),
1258                                                                     CertProvisioningCb);
1259             if(OC_STACK_OK != rst)
1260             {
1261                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "provisionTrustCertChain error: %d", rst);
1262                 return res;
1263             }
1264
1265             std::unique_lock<std::mutex> lck(m_mtx);
1266             m_cond.wait(lck);
1267
1268             if(certResult)
1269             {
1270                 res = ESResult::ES_OK;
1271             }
1272
1273             return res;
1274         }
1275
1276         ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(
1277             std::shared_ptr< OC::OCSecureResource > ownedDevice, std::string& cloudUuid)
1278         {
1279             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performACLProvisioningForCloudServer IN");
1280
1281             ESResult res = ESResult::ES_ACL_PROVISIONING_FAILURE;
1282
1283             if(!ownedDevice)
1284             {
1285                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
1286                 return res;
1287             }
1288
1289             OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "Given cloudUuid: %s", cloudUuid.c_str());
1290
1291             OicUuid_t uuid;
1292             if(OC_STACK_OK != ConvertStrToUuid(cloudUuid.c_str(), &uuid))
1293             {
1294                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
1295                 return res;
1296             }
1297
1298
1299             // Create Acl for Cloud Server to be provisioned to Enrollee
1300             OicSecAcl_t* acl = createAcl(uuid);
1301             if(!acl)
1302             {
1303                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl error return");
1304                 return res;
1305             }
1306
1307             OC::ResultCallBack aclProvisioningCb =
1308                 std::bind(&EnrolleeSecurity::onEnrolleeSecuritySafetyCB,
1309                           std::placeholders::_1, std::placeholders::_2,
1310                           static_cast<ESSecurityCb>(std::bind(&EnrolleeSecurity::aclProvisioningCb,
1311                           this, std::placeholders::_1, std::placeholders::_2)),
1312                           shared_from_this());
1313
1314             // ACL provisioning to Enrollee
1315             OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
1316             if(OC_STACK_OK != rst)
1317             {
1318                 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OCProvisionACL API error: %d", rst);
1319                 return res;
1320             }
1321
1322             std::unique_lock<std::mutex> lck(m_mtx);
1323             m_cond.wait(lck);
1324
1325             if(aclResult)
1326             {
1327                 res = ESResult::ES_OK;
1328             }
1329             OCDeleteACLList(acl);
1330             return res;
1331         }
1332
1333         OicSecAcl_t* EnrolleeSecurity::createAcl(const OicUuid_t cloudUuid)
1334         {
1335             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl IN");
1336
1337             // allocate memory for |acl| struct
1338             OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
1339             if(!acl)
1340             {
1341                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
1342                 return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1343             }
1344             OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
1345             if(!ace)
1346             {
1347                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,  "createAcl: OICCalloc error return");
1348                 return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1349             }
1350             LL_APPEND(acl->aces, ace);
1351
1352             memcpy(&ace->subjectuuid, &cloudUuid, UUID_LENGTH);
1353
1354             OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
1355             if(!rsrc)
1356             {
1357                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
1358                 OCDeleteACLList(acl);
1359                 return NULL;
1360             }
1361
1362             char href[] = "*";
1363             size_t len = strlen(href)+1;  // '1' for null termination
1364             rsrc->href = (char*) OICCalloc(len, sizeof(char));
1365             if(!rsrc->href)
1366             {
1367                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,  "createAcl: OICCalloc error return");
1368                 FreeRsrc(rsrc);
1369                 OCDeleteACLList(acl);
1370                 return NULL;
1371             }
1372             OICStrcpy(rsrc->href, len, href);
1373
1374             size_t arrLen = 1;
1375             rsrc->typeLen = arrLen;
1376             rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
1377             if(!rsrc->types)
1378             {
1379                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,  "createAcl: OICCalloc error return");
1380                 FreeRsrc(rsrc);
1381                 OCDeleteACLList(acl);
1382                 return NULL;
1383             }
1384             rsrc->types[0] = OICStrdup("rt");   // ignore
1385             if(!rsrc->types[0])
1386             {
1387                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,  "createAcl: OICStrdup error return");
1388                 FreeRsrc(rsrc);
1389                 OCDeleteACLList(acl);
1390                 return NULL;
1391             }
1392
1393             rsrc->interfaceLen = 1;
1394             rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
1395             if(!rsrc->interfaces)
1396             {
1397                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,  "createAcl: OICCalloc error return");
1398                 FreeRsrc(rsrc);
1399                 OCDeleteACLList(acl);
1400                 return NULL;
1401             }
1402             rsrc->interfaces[0] = OICStrdup("if");  // ignore
1403             if(!rsrc->interfaces[0])
1404             {
1405                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,  "createAcl: OICStrdup error return");
1406                 FreeRsrc(rsrc);
1407                 OCDeleteACLList(acl);
1408                 return NULL;
1409             }
1410
1411             LL_APPEND(ace->resources, rsrc);
1412
1413             ace->permission = 31;   // R/W/U/D
1414
1415             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl OUT");
1416
1417             return acl;
1418         }
1419
1420         void EnrolleeSecurity::aclProvisioningCb(PMResultList_t *result, int hasError)
1421         {
1422             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "aclProvisioningCb IN");
1423
1424             if (hasError)
1425             {
1426                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "ACL provisioning is failed with code (%d)", hasError);
1427                aclResult = false;
1428             }
1429             else
1430             {
1431                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received ACL provisioning results: ");
1432
1433                std::string devUuid;
1434                for (unsigned int i = 0; i < result->size(); i++)
1435                {
1436                    convertUUIDToString(result->at(i).deviceId.id, devUuid);
1437
1438                    OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
1439                    OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", devUuid.c_str());
1440                }
1441                delete result;
1442                aclResult = true;
1443             }
1444             m_cond.notify_all();
1445         }
1446
1447         void EnrolleeSecurity::certProvisioningCb(PMResultList_t *result, int hasError)
1448         {
1449             OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "certProvisioningCb IN");
1450
1451             if (hasError)
1452             {
1453                OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Cert provisioning is failed with code (%d)", hasError);
1454                certResult = false;
1455             }
1456             else
1457             {
1458                OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received Cert. provisioning results: ");
1459
1460                std::string devUuid;
1461                for (unsigned int i = 0; i < result->size(); i++)
1462                {
1463                    convertUUIDToString(result->at(i).deviceId.id, devUuid);
1464
1465                    OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d", result->at(i).res);
1466                    OIC_LOG_V(INFO_PRIVATE, ENROLEE_SECURITY_TAG, "device uuid : %s", devUuid.c_str());
1467                }
1468                delete result;
1469                certResult= true;
1470             }
1471             m_cond.notify_all();
1472         }
1473 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)
1474     }
1475 }