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 "provisioningdatabasemanager.h"
31 #include "oic_string.h"
33 #include "srmutility.h"
39 #define MAX_PERMISSION_LENGTH (5)
46 #define DISCOVERY_TIMEOUT (10)
48 //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
49 // The value should be accepted from the application as a parameter during ocplatform
51 #define ES_SEC_DISCOVERY_TIMEOUT 5
53 EnrolleeSecurity::EnrolleeSecurity(
54 std::shared_ptr< OC::OCResource > resource,
55 const std::string secDbPath)
58 m_ocResource = resource;
61 void EnrolleeSecurity::registerCallbackHandler(
62 const SecurityProvStatusCb securityProvStatusCb,
63 const SecurityPinCb securityPinCb,
64 const SecProvisioningDbPathCb secProvisioningDbPathCb)
66 m_securityProvStatusCb = securityProvStatusCb;
67 m_securityPinCb = securityPinCb;
68 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
71 std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::findEnrolleeSecurityResource(
74 for (unsigned int i = 0; i < list.size(); i++)
76 if(m_ocResource->sid() == list[i]->getDeviceID().c_str())
78 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
79 list[i]->getDeviceID().c_str());
80 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s",
81 list[i]->getDevAddr().c_str());
85 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! DeviceList_t is NULL");
89 void EnrolleeSecurity::convertUUIDToString(const uint8_t uuid[UUID_SIZE],
90 std::string& uuidString)
92 char uuidArray[UUID_STRING_SIZE] = {'\0',};
93 int ret = snprintf(uuidArray, UUID_STRING_SIZE,
94 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
95 uuid[0], uuid[1], uuid[2], uuid[3],
96 uuid[4], uuid[5], uuid[6], uuid[7],
97 uuid[8], uuid[9], uuid[10], uuid[11],
98 uuid[12], uuid[13], uuid[14], uuid[15]
101 if (ret != UUID_STRING_SIZE - 1)
106 uuidString = uuidArray;
109 void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
113 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
118 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb : Received provisioning results: ");
119 for (unsigned int i = 0; i < result->size(); i++)
121 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
129 ESResult EnrolleeSecurity::provisionOwnership()
131 ESResult res = ESResult::ES_ERROR;
133 OC::DeviceList_t pUnownedDevList, pOwnedDevList;
135 pOwnedDevList.clear();
136 pUnownedDevList.clear();
138 OCStackResult result = OC_STACK_ERROR;
140 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
142 if (result != OC_STACK_OK)
144 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
145 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
148 else if (pOwnedDevList.size())
150 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
151 (int)pOwnedDevList.size());
152 std::shared_ptr< OC::OCSecureResource > ownedDevice =
153 findEnrolleeSecurityResource(pOwnedDevList);
157 if (isOwnedDeviceRegisteredInSVRDB())
159 res = ESResult::ES_OK;
163 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
164 "The found owned device is not in Mediator's PDM.");
165 res = ESResult::ES_ERROR;
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.");
175 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
178 else if (pUnownedDevList.size())
180 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
181 (int)pUnownedDevList.size());
183 m_unownedDevice = findEnrolleeSecurityResource(pUnownedDevList);
186 if(isOwnedDeviceRegisteredInSVRDB())
188 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
189 "Found Unowned device's DevID at DB of ownedDevices list");
191 OC::ResultCallBack removeDeviceWithUuidCB = std::bind(
192 &EnrolleeSecurity::removeDeviceWithUuidCB,
193 this, std::placeholders::_1, std::placeholders::_2);
195 result = OCSecure::removeDeviceWithUuid(DISCOVERY_TIMEOUT,
197 removeDeviceWithUuidCB);
198 if(result != OC_STACK_OK)
200 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid failed.");
201 res = ESResult:: ES_OWNERSHIP_TRANSFER_FAILURE;
205 std::unique_lock<std::mutex> lck(m_mtx);
208 if(!removeDeviceResult)
210 res = ESResult:: ES_OWNERSHIP_TRANSFER_FAILURE;
215 res = performOwnershipTransfer();
217 if(res != ESResult::ES_OK)
219 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
220 res = ESResult:: ES_OWNERSHIP_TRANSFER_FAILURE;
224 std::unique_lock<std::mutex> lck(m_mtx);
229 res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
234 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No matched unowned devices found.");
235 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
240 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unowned devices found.");
241 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
246 ESResult EnrolleeSecurity::performOwnershipTransfer()
248 OCStackResult result = OC_STACK_ERROR;
250 OTMCallbackData_t justWorksCBData;
251 justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
252 justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
253 justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
254 justWorksCBData.createOwnerTransferPayloadCB =
255 CreateJustWorksOwnerTransferPayload;
256 OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
258 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
259 m_unownedDevice->getDeviceID().c_str());
261 OC::ResultCallBack ownershipTransferCb = std::bind(
262 &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
263 std::placeholders::_2);
265 result = m_unownedDevice->doOwnershipTransfer(ownershipTransferCb);
266 if (result != OC_STACK_OK)
268 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is failed");
269 return ESResult::ES_ERROR;
271 return ESResult::ES_OK;
274 void EnrolleeSecurity::removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError)
278 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Error in removeDeviceWithUuid operation!");
279 removeDeviceResult = false;
284 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received provisioning results: ");
286 for (unsigned int i = 0; i < result->size(); i++)
289 convertUUIDToString(result->at(i).deviceId.id, uuid);
291 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG,
292 "Result is = %d for device %s", result->at(i).res, uuid.c_str());
294 removeDeviceResult = true;
299 bool EnrolleeSecurity::isOwnedDeviceRegisteredInSVRDB()
301 OCStackResult res = OC_STACK_ERROR;
303 OCUuidList_t *uuidList = NULL;
304 size_t numOfDevices = 0;
306 res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
307 if (OC_STACK_OK != res)
309 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while getting info from DB");
313 OCUuidList_t *pUuidList = uuidList;
318 convertUUIDToString(pUuidList->dev.id, uuid);
319 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG,
320 "m_ocResource->sid(): %s, cur DB UUID %s",
321 m_ocResource->sid().c_str(), uuid.c_str());
322 if(m_ocResource->sid() == uuid.c_str())
326 pUuidList = pUuidList->next;
332 std::string EnrolleeSecurity::getUUID() const
334 return m_ocResource->sid();
337 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
338 ESResult EnrolleeSecurity::provisionSecurityForCloudServer(
339 std::string cloudUuid, int credId)
341 ESResult res = ESResult::ES_ERROR;
343 // Need to discover Owned device in a given network, again
344 OC::DeviceList_t pOwnedDevList;
345 std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
347 pOwnedDevList.clear();
349 OCStackResult result;
351 result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
353 if (result != OC_STACK_OK)
355 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
356 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
359 else if (pOwnedDevList.size())
361 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
362 (int)pOwnedDevList.size());
363 ownedDevice = findEnrolleeSecurityResource(pOwnedDevList);
367 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found matched owned device.");
368 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
374 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Not found owned devices.");
375 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
379 if(cloudUuid.empty())
381 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
382 "ACL provisioning is skipped due to empty UUID of cloud server");
386 res = performACLProvisioningForCloudServer(ownedDevice, cloudUuid);
387 if(res != ESResult::ES_OK)
389 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "error performACLProvisioningForCloudServer");
396 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
397 "Cert. provisioning is skipped due to wrong cred ID (<1)");
401 res = performCertProvisioningForCloudServer(ownedDevice, credId);
402 if(res != ESResult::ES_OK)
404 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "error performCertProvisioningForCloudServer");
412 ESResult EnrolleeSecurity::performCertProvisioningForCloudServer(
413 std::shared_ptr< OC::OCSecureResource > ownedDevice, int credId)
415 ESResult res = ESResult::ES_CERT_PROVISIONING_FAILURE;
419 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Invalid param");
422 OC::ResultCallBack CertProvisioningCb = std::bind(
423 &EnrolleeSecurity::CertProvisioningCb, this, std::placeholders::_1,
424 std::placeholders::_2);
425 OCStackResult rst = ownedDevice->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
426 static_cast<uint16_t>(credId),
428 if(OC_STACK_OK != rst)
430 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "provisionTrustCertChain error: %d", rst);
434 std::unique_lock<std::mutex> lck(m_mtx);
439 res = ESResult::ES_OK;
445 ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(
446 std::shared_ptr< OC::OCSecureResource > ownedDevice, std::string& cloudUuid)
448 ESResult res = ESResult::ES_ACL_PROVISIONING_FAILURE;
452 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Invalid param");
457 ConvertStrToUuid(cloudUuid.c_str(), &uuid);
459 // Create Acl for Cloud Server to be provisioned to Enrollee
460 OicSecAcl_t* acl = createAcl(uuid);
463 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl error return");
467 OC::ResultCallBack aclProvisioningCb = std::bind(
468 &EnrolleeSecurity::ACLProvisioningCb, this, std::placeholders::_1,
469 std::placeholders::_2);
470 // ACL provisioning to Enrollee
471 OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
472 if(OC_STACK_OK != rst)
474 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OCProvisionACL API error: %d", rst);
478 std::unique_lock<std::mutex> lck(m_mtx);
483 res = ESResult::ES_OK;
489 OicSecAcl_t* EnrolleeSecurity::createAcl(const OicUuid_t cloudUuid)
491 // allocate memory for |acl| struct
492 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
495 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
496 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
498 OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
501 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
502 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
504 LL_APPEND(acl->aces, ace);
506 memcpy(&ace->subjectuuid, &cloudUuid, UUID_LENGTH);
508 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
511 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
512 OCDeleteACLList(acl);
517 size_t len = strlen(href)+1; // '1' for null termination
518 rsrc->href = (char*) OICCalloc(len, sizeof(char));
521 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "createAcl: OICCalloc error return");
522 OCDeleteACLList(acl);
525 OICStrcpy(rsrc->href, len, href);
528 rsrc->typeLen = arrLen;
529 rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
530 rsrc->interfaceLen = 1;
531 rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
532 rsrc->types[0] = OICStrdup("rt"); // ignore
533 rsrc->interfaces[0] = OICStrdup("if"); // ignore
535 LL_APPEND(ace->resources, rsrc);
537 ace->permission = 31; // R/W/U/D
542 void EnrolleeSecurity::ACLProvisioningCb(PMResultList_t *result, int hasError)
546 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Error in ACL provisioning operation!");
551 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received ACL provisioning results: ");
554 for (unsigned int i = 0; i < result->size(); i++)
556 convertUUIDToString(result->at(i).deviceId.id, devUuid);
557 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device %s",
558 result->at(i).res, devUuid.c_str());
566 void EnrolleeSecurity::CertProvisioningCb(PMResultList_t *result, int hasError)
570 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Error in Cert. provisioning operation!");
575 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received Cert. provisioning results: ");
578 for (unsigned int i = 0; i < result->size(); i++)
580 convertUUIDToString(result->at(i).deviceId.id, devUuid);
581 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device %s",
582 result->at(i).res, devUuid.c_str());
589 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)