1 //******************************************************************
\r
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
\r
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
7 // Licensed under the Apache License, Version 2.0 (the "License");
\r
8 // you may not use this file except in compliance with the License.
\r
9 // You may obtain a copy of the License at
\r
11 // http://www.apache.org/licenses/LICENSE-2.0
\r
13 // Unless required by applicable law or agreed to in writing, software
\r
14 // distributed under the License is distributed on an "AS IS" BASIS,
\r
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 // See the License for the specific language governing permissions and
\r
17 // limitations under the License.
\r
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
23 #include "EnrolleeSecurity.h"
\r
24 #include "oxmjustworks.h"
\r
25 #include "oxmrandompin.h"
\r
26 #include "RemoteEnrolleeResource.h"
\r
28 #include "ESException.h"
\r
29 #include "oic_malloc.h"
\r
30 #include "oic_string.h"
\r
36 #define MAX_PERMISSION_LENGTH (5)
\r
44 //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
\r
45 // The value should be accepted from the application as a parameter during ocplatform
\r
47 #define ES_SEC_DISCOVERY_TIMEOUT 5
\r
49 EnrolleeSecurity::EnrolleeSecurity(
\r
50 std::shared_ptr< RemoteEnrolleeResource > remoteEnrolleeResource,
\r
51 std::string secDbPath)
\r
53 m_enrolleeSecState = EnrolleeSecState::ES_SEC_UNKNOWN;
\r
54 m_remoteEnrolleeResource = remoteEnrolleeResource;
\r
56 //Initializing the provisioning client stack using the db path provided by the
\r
58 // Note : If the path is NULL or empty, the PDM.db should be present in the same path.
\r
59 OCStackResult result = OCSecure::provisionInit(secDbPath);
\r
61 if (result != OC_STACK_OK)
\r
63 throw ESPlatformException(result);
\r
67 ESResult EnrolleeSecurity::registerCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb,
\r
68 SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb)
\r
71 m_enrolleeSecStatusCb = enrolleeSecStatusCb;
\r
72 m_securityPinCb = securityPinCb;
\r
73 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
\r
78 std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::findEnrollee(std::string host,
\r
81 for (unsigned int i = 0; i < list.size(); i++)
\r
83 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
\r
84 list[i]->getDeviceID().c_str());OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str());
\r
86 if (list[i]->getDevAddr() == host)
\r
95 void EnrolleeSecurity::convertUUIDToString(OicUuid_t uuid, std::string& uuidString)
\r
97 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =
\r
99 uint32_t outLen = 0;
\r
100 B64Result b64Ret = B64_OK;
\r
101 std::ostringstream deviceId("");
\r
103 b64Ret = b64Encode(uuid.id, sizeof(uuid.id),
\r
104 base64Buff, sizeof(base64Buff), &outLen);
\r
106 if (B64_OK == b64Ret)
\r
108 deviceId << base64Buff;
\r
110 uuidString = deviceId.str();
\r
113 void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
\r
117 OC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
\r
119 std::shared_ptr< SecProvisioningResult > securityProvisioningStatus = nullptr;
\r
121 convertUUIDToString(result->at(0).deviceId, uuid);
\r
122 securityProvisioningStatus = std::make_shared< SecProvisioningResult >(uuid,
\r
125 m_enrolleeSecStatusCb(securityProvisioningStatus);
\r
130 OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,"Transferred Ownership successfuly for device : ");
\r
132 convertUUIDToString(result->at(0).deviceId, uuid);
\r
133 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
\r
135 //TODO : Decide if we have to manage the owned/unowned devices.
\r
136 //pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
\r
137 //pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
\r
139 OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
\r
140 "Ownership transfer success success. Continuing with provisioning ACL");
\r
142 if (provisionAcl() == ES_ERROR)
\r
144 OC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in provisionAcl");
\r
145 std::shared_ptr< SecProvisioningResult > securityProvisioningStatus = nullptr;
\r
147 convertUUIDToString(result->at(0).deviceId, uuid);
\r
148 securityProvisioningStatus = std::make_shared< SecProvisioningResult >(uuid,
\r
157 * Callback function for provisioning ACL, Credentials.
\r
159 * @param[in] result Result list
\r
160 * @param[in] hasError indicates if the result has error
\r
162 void EnrolleeSecurity::provisionCb(OC::PMResultList_t *result, int hasError)
\r
166 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionCb : Error in provisioning operation!");
\r
170 OC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionCb : Received provisioning results: ");
\r
171 for (unsigned int i = 0; i < result->size(); i++)
\r
173 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
\r
175 convertUUIDToString(result->at(0).deviceId, uuid);
\r
177 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
\r
178 std::shared_ptr< SecProvisioningResult > securityProvisioningStatus = nullptr;
\r
179 securityProvisioningStatus = std::make_shared< SecProvisioningResult >(uuid,
\r
182 m_enrolleeSecStatusCb(securityProvisioningStatus);
\r
191 * Calculate ACL permission from string to bit
\r
193 * @param[in] temp_psm Input data of ACL permission string
\r
194 * @param[in,out] pms The pointer of ACL permission value
\r
195 * @return 0 on success otherwise -1.
\r
197 int EnrolleeSecurity::CalculateAclPermission(const char *temp_pms, uint16_t *pms)
\r
201 if (NULL == temp_pms || NULL == pms)
\r
206 while (temp_pms[i] != '\0')
\r
208 switch (temp_pms[i])
\r
254 EasySetupState EnrolleeSecurity::performOwnershipTransfer()
\r
256 EasySetupState ownershipStatus = DEVICE_NOT_OWNED;
\r
258 OC::DeviceList_t pUnownedDevList, pOwnedDevList;
\r
260 pOwnedDevList.clear();
\r
261 pUnownedDevList.clear();
\r
263 OCStackResult result;
\r
265 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
\r
267 if (result != OC_STACK_OK)
\r
269 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
\r
270 ownershipStatus = DEVICE_NOT_OWNED;
\r
272 throw ESPlatformException(result);
\r
273 return ownershipStatus;
\r
275 else if (pOwnedDevList.size())
\r
277 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
\r
278 pOwnedDevList.size());
\r
279 std::shared_ptr< OC::OCSecureResource > ownedDevice =
\r
282 m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress),
\r
286 ownershipStatus = DEVICE_OWNED;
\r
287 return ownershipStatus;
\r
292 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No owned devices found.");
\r
293 ownershipStatus = DEVICE_NOT_OWNED;
\r
296 result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);
\r
297 if (result != OC_STACK_OK)
\r
299 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");
\r
300 ownershipStatus = DEVICE_NOT_OWNED;
\r
302 throw ESPlatformException(result);
\r
303 return ownershipStatus;
\r
305 else if (pUnownedDevList.size())
\r
307 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
\r
308 pUnownedDevList.size());
\r
312 m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress,
\r
314 if (m_unownedDevice)
\r
316 OTMCallbackData_t justWorksCBData;
\r
317 justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
\r
318 justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
\r
319 justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
\r
320 justWorksCBData.createOwnerTransferPayloadCB =
\r
321 CreateJustWorksOwnerTransferPayload;
\r
322 OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
\r
324 OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
\r
325 m_unownedDevice->getDeviceID().c_str());
\r
327 OC::ResultCallBack ownershipTransferCb = std::bind(
\r
328 &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
\r
329 std::placeholders::_2);
\r
331 if (m_unownedDevice->doOwnershipTransfer(ownershipTransferCb) != OC_STACK_OK)
\r
333 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");
\r
334 ownershipStatus = DEVICE_NOT_OWNED;
\r
336 throw ESPlatformException(result);
\r
338 ownershipStatus = DEVICE_NOT_OWNED;
\r
343 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unSecure devices found.");
\r
344 ownershipStatus = DEVICE_NOT_OWNED;
\r
346 return ownershipStatus;
\r
349 return ownershipStatus;
\r
352 ESResult EnrolleeSecurity::createProvisiongResourceACL(OicSecAcl_t *acl)
\r
354 //TODO : Have to accept subject id of the mediator from application during easysetup
\r
356 char temp_id[UUID_LENGTH+1] = {"admindeviceUUID0"};
\r
357 for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
\r
359 acl->subject.id[j++] = temp_id[i];
\r
362 //Always resource length is 1. /oic/prov is the only resource for which needs ACL
\r
363 // permission has to be set
\r
364 acl->resourcesLen = 1;
\r
365 acl->resources = (char **) OICCalloc(acl->resourcesLen, sizeof(char *));
\r
366 if (NULL == acl->resources)
\r
368 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");
\r
372 char temp_rsc[MAX_URI_LENGTH] = {OC_RSRVD_ES_URI_PROV};
\r
374 for (size_t i = 0; i < acl->resourcesLen; i++)
\r
376 acl->resources[i] = OICStrdup(temp_rsc);
\r
377 if (NULL == acl->resources[i])
\r
379 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");
\r
384 char temp_pms[MAX_PERMISSION_LENGTH+1]={"CRUDN"};
\r
388 ret = CalculateAclPermission(temp_pms, &(acl->permission));
\r
389 } while (0 != ret);
\r
391 //TODO : Have to accept subject id of the mediator from application during easysetup
\r
393 for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
\r
395 acl->subject.id[j++] = temp_id[i];
\r
399 acl->ownersLen = 1;//Always resource owner is only one, which is the mediator
\r
400 acl->owners = (OicUuid_t *) OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
\r
401 if (NULL == acl->owners)
\r
403 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");
\r
406 for (size_t i = 0; i < acl->ownersLen; i++)
\r
408 for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
\r
410 acl->owners[i].id[j++] = temp_id[k];
\r
416 ESResult EnrolleeSecurity::provisionAcl()
\r
418 // TODO : Currently device uuid is hardcoded, but this id has to be obtained from the
\r
420 OicSecAcl_t *acl = nullptr;
\r
422 acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
\r
423 if (nullptr == acl)
\r
425 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation");
\r
429 if ( createProvisiongResourceACL (acl) == ES_ERROR)
\r
435 OC::ResultCallBack provisioningCb = std::bind(&EnrolleeSecurity::provisionCb, this,
\r
436 std::placeholders::_1, std::placeholders::_2);
\r
438 if (m_unownedDevice->provisionACL(acl, provisioningCb) != OC_STACK_OK)
\r
440 OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionACL is failed");
\r