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 const std::string secDbPath)
55 m_ocResource = resource;
58 void EnrolleeSecurity::registerCallbackHandler(
59 const SecurityProvStatusCb securityProvStatusCb,
60 const SecurityPinCb securityPinCb,
61 const SecProvisioningDbPathCb secProvisioningDbPathCb)
63 m_securityProvStatusCb = securityProvStatusCb;
64 m_securityPinCb = securityPinCb;
65 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
68 std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::getEnrollee(
71 for (unsigned int i = 0; i < list.size(); i++)
73 if(m_ocResource->sid() == list[i]->getDeviceID().c_str())
75 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
76 list[i]->getDeviceID().c_str());
77 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s",
78 list[i]->getDevAddr().c_str());
82 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! DeviceList_t is NULL");
86 void EnrolleeSecurity::convertUUIDToString(const OicUuid_t uuid,
87 std::string& uuidString)
89 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =
92 B64Result b64Ret = B64_OK;
93 std::ostringstream deviceId("");
95 b64Ret = b64Encode(uuid.id, sizeof(uuid.id),
96 base64Buff, sizeof(base64Buff), &outLen);
100 deviceId << base64Buff;
102 uuidString = deviceId.str();
105 void EnrolleeSecurity::convertStringToUUID(OicUuid_t& uuid,
106 const std::string uuidString)
108 size_t outBufSize = B64DECODE_OUT_SAFESIZE((uuidString.length() + 1));
109 uint8_t* outKey = (uint8_t*)OICCalloc(1, outBufSize);
110 uint32_t outKeySize = 0;
113 OIC_LOG (ERROR, ENROLEE_SECURITY_TAG, "Failed to memoray allocation.");
114 throw ESBadRequestException ("Failed to memoray allocation.");
117 if(B64_OK == b64Decode((char*)uuidString.c_str(),
123 memcpy(uuid.id, outKey, outKeySize);
127 OIC_LOG (ERROR, ENROLEE_SECURITY_TAG, "Failed to base64 decoding.");
128 throw ESBadRequestException ("Failed to base64 decoding.");
134 void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
138 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
141 convertUUIDToString(result->at(0).deviceId, uuid);
142 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
143 std::make_shared< SecProvisioningStatus >(uuid, ES_ERROR);
144 m_securityProvStatusCb(securityProvisioningStatus);
149 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb : Received provisioning results: ");
150 for (unsigned int i = 0; i < result->size(); i++)
152 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
154 convertUUIDToString(result->at(0).deviceId, uuid);
156 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
157 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
158 std::make_shared< SecProvisioningStatus >(uuid, ES_OK);
159 m_securityProvStatusCb(securityProvisioningStatus);
167 void EnrolleeSecurity::performOwnershipTransfer()
169 OC::DeviceList_t pUnownedDevList, pOwnedDevList;
171 pOwnedDevList.clear();
172 pUnownedDevList.clear();
174 OCStackResult result = OC_STACK_ERROR;
176 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
178 if (result != OC_STACK_OK)
180 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
182 throw ESPlatformException(result);
184 else if (pOwnedDevList.size())
186 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
187 pOwnedDevList.size());
188 std::shared_ptr< OC::OCSecureResource > ownedDevice = getEnrollee(pOwnedDevList);
192 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
193 std::make_shared< SecProvisioningStatus >(ownedDevice->getDeviceID(), ES_OK);
194 m_securityProvStatusCb(securityProvisioningStatus);
199 result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);
200 if (result != OC_STACK_OK)
202 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");
204 throw ESPlatformException(result);
206 else if (pUnownedDevList.size())
208 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
209 pUnownedDevList.size());
211 m_unownedDevice = getEnrollee(pUnownedDevList);
214 OTMCallbackData_t justWorksCBData;
215 justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
216 justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
217 justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
218 justWorksCBData.createOwnerTransferPayloadCB =
219 CreateJustWorksOwnerTransferPayload;
220 OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
222 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
223 m_unownedDevice->getDeviceID().c_str());
225 OC::ResultCallBack ownershipTransferCb = std::bind(
226 &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
227 std::placeholders::_2);
229 result = m_unownedDevice->doOwnershipTransfer(ownershipTransferCb);
230 if (result != OC_STACK_OK)
232 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");
233 throw ESPlatformException(result);
238 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No matched unowned devices found.");
239 throw ESException("No matched unowned devices found.");
244 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unowned devices found.");
245 throw ESException("No unowned devices found.");
249 ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(std::string cloudUuid)
251 ESResult res = ESResult::ES_ERROR;
254 convertStringToUUID(uuid, cloudUuid);
256 // Need to discover Owned device in a given network, again
257 OC::DeviceList_t pOwnedDevList;
258 std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
260 pOwnedDevList.clear();
262 OCStackResult result;
264 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
266 if (result != OC_STACK_OK)
268 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
270 throw ESPlatformException(result);
272 else if (pOwnedDevList.size())
274 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
275 pOwnedDevList.size());
276 ownedDevice = getEnrollee(pOwnedDevList);
280 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
286 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
290 // Create Acl for Cloud Server to be provisioned to Enrollee
291 OicSecAcl_t* acl = createAcl(uuid);
294 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl error return");
298 OC::ResultCallBack aclProvisioningCb = std::bind(
299 &EnrolleeSecurity::ACLProvisioningCb, this, std::placeholders::_1,
300 std::placeholders::_2);
301 // ACL provisioning to Enrollee
302 OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
303 if(OC_STACK_OK != rst)
305 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OCProvisionACL API error: %d", rst);
309 std::unique_lock<std::mutex> lck(m_mtx);
310 m_cond.wait_for(lck, std::chrono::seconds(ES_SEC_DISCOVERY_TIMEOUT));
314 res = ESResult::ES_OK;
320 std::string EnrolleeSecurity::getUUID() const
322 return m_ocResource->sid();
325 OicSecAcl_t* EnrolleeSecurity::createAcl(const OicUuid_t cloudUuid)
327 // allocate memory for |acl| struct
328 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
331 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
332 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
334 OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
337 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
338 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
340 LL_APPEND(acl->aces, ace);
342 memcpy(&ace->subjectuuid, &cloudUuid, UUID_LENGTH);
344 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
347 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
348 OCDeleteACLList(acl);
353 size_t len = strlen(href)+1; // '1' for null termination
354 rsrc->href = (char*) OICCalloc(len, sizeof(char));
357 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
358 OCDeleteACLList(acl);
361 OICStrcpy(rsrc->href, len, href);
364 rsrc->typeLen = arrLen;
365 rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
366 rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
367 rsrc->types[0] = OICStrdup("rt"); // ignore
368 rsrc->interfaces[0] = OICStrdup("if"); // ignore
370 LL_APPEND(ace->resources, rsrc);
372 ace->permission = 31; // R/W/U/D
377 void EnrolleeSecurity::ACLProvisioningCb(PMResultList_t *result, int hasError)
381 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Error in provisioning operation!");
386 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received provisioning results: ");
389 for (unsigned int i = 0; i < result->size(); i++)
391 convertUUIDToString(result->at(i).deviceId, devUuid);
392 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device %s",
393 result->at(i).res, devUuid.c_str());