1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
23 #include "EnrolleeSecurity.h"
24 #include "oxmjustworks.h"
25 #include "oxmrandompin.h"
26 #include "EnrolleeResource.h"
28 #include "ESException.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
37 #define MAX_PERMISSION_LENGTH (5)
45 //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
46 // The value should be accepted from the application as a parameter during ocplatform
48 #define ES_SEC_DISCOVERY_TIMEOUT 5
50 EnrolleeSecurity::EnrolleeSecurity(
51 std::shared_ptr< OC::OCResource > resource,
52 std::string secDbPath)
55 m_ocResource = resource;
58 void EnrolleeSecurity::registerCallbackHandler(SecurityProvStatusCb securityProvStatusCb,
59 SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb)
61 m_securityProvStatusCb = securityProvStatusCb;
62 m_securityPinCb = securityPinCb;
63 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
66 std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::getEnrollee(DeviceList_t &list)
68 for (unsigned int i = 0; i < list.size(); i++)
70 if(m_ocResource->sid() == list[i]->getDeviceID().c_str())
72 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
73 list[i]->getDeviceID().c_str());
74 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str());
77 //Always return the first element of the unOwned devices. This is considering that Mediator is
78 // always connected with only one Enrollee for which ownership transfer is being performed.
79 // Incase of multiple Enrollee devices connected to the Mediator via any OnBoarding method (SoftAp
80 // for example), the Enrollee devices will be provisioned in the first come first serve basis in the order
81 // returned by the security layer.
84 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! DeviceList_t is NULL");
88 void EnrolleeSecurity::convertUUIDToString(OicUuid_t uuid, std::string& uuidString)
90 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =
93 B64Result b64Ret = B64_OK;
94 std::ostringstream deviceId("");
96 b64Ret = b64Encode(uuid.id, sizeof(uuid.id),
97 base64Buff, sizeof(base64Buff), &outLen);
101 deviceId << base64Buff;
103 uuidString = deviceId.str();
106 void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
110 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
113 convertUUIDToString(result->at(0).deviceId, uuid);
114 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
115 std::make_shared< SecProvisioningStatus >(uuid, ES_ERROR);
116 m_securityProvStatusCb(securityProvisioningStatus);
121 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb : Received provisioning results: ");
122 for (unsigned int i = 0; i < result->size(); i++)
124 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
126 convertUUIDToString(result->at(0).deviceId, uuid);
128 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
129 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
130 std::make_shared< SecProvisioningStatus >(uuid, ES_OK);
131 m_securityProvStatusCb(securityProvisioningStatus);
139 void EnrolleeSecurity::performOwnershipTransfer()
141 OC::DeviceList_t pUnownedDevList, pOwnedDevList;
143 pOwnedDevList.clear();
144 pUnownedDevList.clear();
146 OCStackResult result;
148 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
150 if (result != OC_STACK_OK)
152 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
154 throw ESPlatformException(result);
156 else if (pOwnedDevList.size())
158 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
159 pOwnedDevList.size());
160 std::shared_ptr< OC::OCSecureResource > ownedDevice = getEnrollee(pOwnedDevList);
164 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
165 std::make_shared< SecProvisioningStatus >(ownedDevice->getDeviceID(), ES_OK);
166 m_securityProvStatusCb(securityProvisioningStatus);
171 result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);
172 if (result != OC_STACK_OK)
174 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");
176 throw ESPlatformException(result);
178 else if (pUnownedDevList.size())
180 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
181 pUnownedDevList.size());
183 m_unownedDevice = getEnrollee(pUnownedDevList);
186 OTMCallbackData_t justWorksCBData;
187 justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
188 justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
189 justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
190 justWorksCBData.createOwnerTransferPayloadCB =
191 CreateJustWorksOwnerTransferPayload;
192 OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
194 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
195 m_unownedDevice->getDeviceID().c_str());
197 OC::ResultCallBack ownershipTransferCb = std::bind(
198 &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
199 std::placeholders::_2);
201 result = m_unownedDevice->doOwnershipTransfer(ownershipTransferCb);
202 if (result != OC_STACK_OK)
204 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");
205 throw ESPlatformException(result);
211 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unOwned devices found.");
212 throw ESException("No unOwned devices found.");
216 void EnrolleeSecurity::performACLProvisioningForCloudServer(OicUuid_t serverUuid)
218 // Need to discover Owned device in a given network, again
219 OC::DeviceList_t pOwnedDevList;
220 std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
222 pOwnedDevList.clear();
224 OCStackResult result;
226 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
228 if (result != OC_STACK_OK)
230 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
232 throw ESPlatformException(result);
234 else if (pOwnedDevList.size())
236 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
237 pOwnedDevList.size());
238 ownedDevice = getEnrollee(pOwnedDevList);
242 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
248 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
252 // Create Acl for Cloud Server to be provisioned to Enrollee
253 OicSecAcl_t* acl = createAcl(serverUuid);
256 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl error return");
260 OC::ResultCallBack aclProvisioningCb = std::bind(
261 &EnrolleeSecurity::ACLProvisioningCb, this, std::placeholders::_1,
262 std::placeholders::_2);
263 // ACL provisioning to Enrollee
264 OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
265 if(OC_STACK_OK != rst)
267 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OCProvisionACL API error: %d", rst);
272 OicSecAcl_t* EnrolleeSecurity::createAcl(OicUuid_t serverUuid)
274 // allocate memory for |acl| struct
275 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
278 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
279 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
281 OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
284 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
285 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
287 LL_APPEND(acl->aces, ace);
289 memcpy(&ace->subjectuuid, &serverUuid, UUID_LENGTH);
291 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
294 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
295 OCDeleteACLList(acl);
300 size_t len = strlen(href)+1; // '1' for null termination
301 rsrc->href = (char*) OICCalloc(len, sizeof(char));
304 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
305 OCDeleteACLList(acl);
308 OICStrcpy(rsrc->href, len, href);
311 rsrc->typeLen = arrLen;
312 rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
313 rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
314 rsrc->types[0] = OICStrdup("rt"); // ignore
315 rsrc->interfaces[0] = OICStrdup("if"); // ignore
317 LL_APPEND(ace->resources, rsrc);
319 ace->permission = 31; // R/W/U/D
324 void EnrolleeSecurity::ACLProvisioningCb(PMResultList_t *result, int hasError)