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)
47 // TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
48 // The value should be accepted from the application as a parameter during ocplatform
50 #define ES_SEC_DISCOVERY_TIMEOUT 5
52 EnrolleeSecurity::EnrolleeSecurity(
53 std::shared_ptr< OC::OCResource > resource,
54 const std::string secDbPath)
57 m_ocResource = resource;
60 void EnrolleeSecurity::convertUUIDToString(const uint8_t uuid[UUID_SIZE],
61 std::string& uuidString)
63 char uuidArray[UUID_STRING_SIZE] = {'\0',};
64 int ret = snprintf(uuidArray, UUID_STRING_SIZE,
65 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
66 uuid[0], uuid[1], uuid[2], uuid[3],
67 uuid[4], uuid[5], uuid[6], uuid[7],
68 uuid[8], uuid[9], uuid[10], uuid[11],
69 uuid[12], uuid[13], uuid[14], uuid[15]
72 if (ret != UUID_STRING_SIZE - 1)
77 uuidString = uuidArray;
80 void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
82 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb IN");
85 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransfer is failed with code(%d)", hasError);
90 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "OwnershipTransfer is succeeded");
91 for (unsigned int i = 0; i < result->size(); i++)
93 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device", result->at(i).res);
101 ESResult EnrolleeSecurity::provisionOwnership()
103 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionOwnership IN");
105 ESResult res = ESResult::ES_ERROR;
107 OCStackResult result = OC_STACK_ERROR;
109 if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
111 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
115 result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
118 if (result != OC_STACK_OK)
120 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Secure Resource Discovery failed.");
121 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
124 else if (m_securedResource)
126 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
127 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", m_securedResource->getDevAddr().c_str());
128 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "SID: %s", m_securedResource->getDeviceID().c_str());
129 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", m_securedResource->getOwnedStatus());
131 if (m_securedResource->getOwnedStatus()) // owned check logic
133 if(isOwnedDeviceRegisteredInSVRDB())
135 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
136 "The found device is already owned by Mediator.(SUCCESS)");
137 res = ESResult::ES_OK;
141 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
142 res = ESResult::ES_ERROR;
146 else // unowned check logic
148 if(isOwnedDeviceRegisteredInSVRDB())
150 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG,
151 "Found Unowned device's DevID at DB of ownedDevices list");
153 OC::ResultCallBack removeDeviceWithUuidCB = std::bind(
154 &EnrolleeSecurity::removeDeviceWithUuidCB,
155 this, std::placeholders::_1, std::placeholders::_2);
157 result = OCSecure::removeDeviceWithUuid(ES_SEC_DISCOVERY_TIMEOUT,
159 removeDeviceWithUuidCB);
160 if(result != OC_STACK_OK)
162 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid failed. (%d)", result);
163 res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
167 std::unique_lock<std::mutex> lck(m_mtx);
168 m_cond.wait_for(lck, std::chrono::seconds(ES_SEC_DISCOVERY_TIMEOUT));
170 if(!removeDeviceResult)
172 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Removing device is failed.");
173 res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
176 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Removing device is succeeded.");
179 res = performOwnershipTransfer();
181 if(res != ESResult::ES_OK)
183 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed. (%d)", res);
184 res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
188 std::unique_lock<std::mutex> lck(m_mtx);
193 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownership-Transfer failed.");
194 res = ESResult::ES_OWNERSHIP_TRANSFER_FAILURE;
200 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found.");
201 res = ESResult:: ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
206 ESResult EnrolleeSecurity::performOwnershipTransfer()
208 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performOwnershipTransfer IN.");
210 OCStackResult result = OC_STACK_ERROR;
212 OTMCallbackData_t justWorksCBData;
213 justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
214 justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
215 justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
216 justWorksCBData.createOwnerTransferPayloadCB =
217 CreateJustWorksOwnerTransferPayload;
218 OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
220 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
221 m_securedResource->getDeviceID().c_str());
223 OC::ResultCallBack ownershipTransferCb = std::bind(
224 &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
225 std::placeholders::_2);
227 result = m_securedResource->doOwnershipTransfer(ownershipTransferCb);
228 if (result != OC_STACK_OK)
230 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "doOwnershipTransfer is failed");
231 return ESResult::ES_ERROR;
233 return ESResult::ES_OK;
236 void EnrolleeSecurity::removeDeviceWithUuidCB(OC::PMResultList_t *result, int hasError)
238 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuidCB IN");
242 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is failed with code (%d)", hasError);
243 removeDeviceResult = false;
248 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "removeDeviceWithUuid is succeeded");
250 for (unsigned int i = 0; i < result->size(); i++)
253 convertUUIDToString(result->at(i).deviceId.id, uuid);
255 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG,
256 "Result is = %d for device %s", result->at(i).res, uuid.c_str());
258 removeDeviceResult = true;
263 bool EnrolleeSecurity::isOwnedDeviceRegisteredInSVRDB()
265 OCStackResult res = OC_STACK_ERROR;
267 OCUuidList_t *uuidList = NULL;
268 size_t numOfDevices = 0;
270 res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
271 if (OC_STACK_OK != res)
273 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while getting info from DB");
277 OCUuidList_t *pUuidList = uuidList;
281 convertUUIDToString(pUuidList->dev.id, uuid);
282 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG,
283 "m_ocResource->sid(): %s, cur DB UUID %s",
284 m_ocResource->sid().c_str(), uuid.c_str());
285 if(m_ocResource->sid() == uuid.c_str())
290 pUuidList = pUuidList->next;
297 std::string EnrolleeSecurity::getUUID() const
299 return m_ocResource->sid();
302 #if defined(__WITH_DTLS__) && defined(__WITH_TLS__)
303 ESResult EnrolleeSecurity::provisionSecurityForCloudServer(
304 std::string cloudUuid, int credId)
306 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "provisionSecurityForCloudServer IN");
308 ESResult res = ESResult::ES_ERROR;
310 // Need to discover Owned device in a given network, again
311 std::shared_ptr< OC::OCSecureResource > ownedDevice = NULL;
313 OCStackResult result;
315 if(OC_STACK_OK != ConvertStrToUuid(m_ocResource->sid().c_str(), &uuid))
317 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
322 result = OCSecure::discoverSingleDevice(ES_SEC_DISCOVERY_TIMEOUT,
325 if (result != OC_STACK_OK)
327 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "secureResource Discovery failed.");
328 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
331 else if (ownedDevice)
333 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Secured resource is found.");
334 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "HOST: %s", ownedDevice->getDevAddr().c_str());
335 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "SID: %s", ownedDevice->getDeviceID().c_str());
336 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Owned status: %d", ownedDevice->getOwnedStatus());
338 if (ownedDevice->getOwnedStatus())
340 if(!isOwnedDeviceRegisteredInSVRDB())
342 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is not one in SVR DB");
343 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
349 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "The found device is unowned.");
350 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Ownerthip transfer is required.");
352 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
358 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No secure resource is found");
359 res = ESResult::ES_SECURE_RESOURCE_DISCOVERY_FAILURE;
363 if(cloudUuid.empty())
365 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
366 "ACL provisioning is skipped due to empty UUID of cloud server");
370 res = performACLProvisioningForCloudServer(ownedDevice, cloudUuid);
371 if(res != ESResult::ES_OK)
373 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performACLProvisioningForCloudServer");
380 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,
381 "Cert. provisioning is skipped due to wrong cred ID (<1)");
385 res = performCertProvisioningForCloudServer(ownedDevice, credId);
386 if(res != ESResult::ES_OK)
388 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "error performCertProvisioningForCloudServer");
396 ESResult EnrolleeSecurity::performCertProvisioningForCloudServer(
397 std::shared_ptr< OC::OCSecureResource > ownedDevice, int credId)
399 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performCertProvisioningForCloudServer IN");
401 ESResult res = ESResult::ES_CERT_PROVISIONING_FAILURE;
405 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
409 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Given CredId: %d", credId);
411 OC::ResultCallBack CertProvisioningCb = std::bind(
412 &EnrolleeSecurity::CertProvisioningCb, this, std::placeholders::_1,
413 std::placeholders::_2);
414 OCStackResult rst = ownedDevice->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
415 static_cast<uint16_t>(credId),
417 if(OC_STACK_OK != rst)
419 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "provisionTrustCertChain error: %d", rst);
423 std::unique_lock<std::mutex> lck(m_mtx);
428 res = ESResult::ES_OK;
434 ESResult EnrolleeSecurity::performACLProvisioningForCloudServer(
435 std::shared_ptr< OC::OCSecureResource > ownedDevice, std::string& cloudUuid)
437 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "performACLProvisioningForCloudServer IN");
439 ESResult res = ESResult::ES_ACL_PROVISIONING_FAILURE;
443 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Given ownedDevice is null");
447 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Given cloudUuid: %s", cloudUuid.c_str());
450 if(OC_STACK_OK != ConvertStrToUuid(cloudUuid.c_str(), &uuid))
452 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Convert to uuid from deviceID failed.");
457 // Create Acl for Cloud Server to be provisioned to Enrollee
458 OicSecAcl_t* acl = createAcl(uuid);
461 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "createAcl error return");
465 OC::ResultCallBack aclProvisioningCb = std::bind(
466 &EnrolleeSecurity::ACLProvisioningCb, this, std::placeholders::_1,
467 std::placeholders::_2);
468 // ACL provisioning to Enrollee
469 OCStackResult rst = ownedDevice->provisionACL(acl, aclProvisioningCb);
470 if(OC_STACK_OK != rst)
472 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "OCProvisionACL API error: %d", rst);
476 std::unique_lock<std::mutex> lck(m_mtx);
481 res = ESResult::ES_OK;
487 OicSecAcl_t* EnrolleeSecurity::createAcl(const OicUuid_t cloudUuid)
489 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl IN");
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
539 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "creatAcl OUT");
544 void EnrolleeSecurity::ACLProvisioningCb(PMResultList_t *result, int hasError)
546 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ACLProvisioningCb IN");
550 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "ACL provisioning is failed with code (%d)", hasError);
555 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received ACL provisioning results: ");
558 for (unsigned int i = 0; i < result->size(); i++)
560 convertUUIDToString(result->at(i).deviceId.id, devUuid);
561 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device %s",
562 result->at(i).res, devUuid.c_str());
570 void EnrolleeSecurity::CertProvisioningCb(PMResultList_t *result, int hasError)
572 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "CertProvisioningCb IN");
576 OIC_LOG_V(ERROR, ENROLEE_SECURITY_TAG, "Cert provisioning is failed with code (%d)", hasError);
581 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received Cert. provisioning results: ");
584 for (unsigned int i = 0; i < result->size(); i++)
586 convertUUIDToString(result->at(i).deviceId.id, devUuid);
587 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device %s",
588 result->at(i).res, devUuid.c_str());
595 #endif //defined(__WITH_DTLS__) && defined(__WITH_TLS__)