1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH 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 "oic_malloc.h"
25 #include "resourcemanager.h"
26 #include "doxmresource.h"
27 #include "pstatresource.h"
28 #include "aclresource.h"
29 #include "psinterface.h"
31 #include "srmresourcestrings.h"
32 #include "securevirtualresourcetypes.h"
35 #include "cainterface.h"
36 #include "credresource.h"
37 #include "ocserverrequest.h"
38 #include "srmutility.h"
39 #include "pinoxmcommon.h"
52 #define TAG "SRM-DOXM"
54 static OicSecDoxm_t *gDoxm = NULL;
55 static OCResourceHandle gDoxmHandle = NULL;
57 static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
58 static OicSecDoxm_t gDefaultDoxm =
60 NULL, /* OicUrn_t *oxmType */
61 0, /* size_t oxmTypeLen */
62 &gOicSecDoxmJustWorks, /* uint16_t *oxm */
63 1, /* size_t oxmLen */
64 OIC_JUST_WORKS, /* uint16_t oxmSel */
65 SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
66 false, /* bool owned */
67 {.id = {0}}, /* OicUuid_t deviceID */
68 {.id = {0}}, /* OicUuid_t owner */
71 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
76 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
78 OICFree(doxm->oxmType[i]);
80 OICFree(doxm->oxmType);
90 char * BinToDoxmJSON(const OicSecDoxm_t * doxm)
98 cJSON *jsonDoxm = NULL;
99 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
101 B64Result b64Ret = B64_OK;
103 cJSON *jsonRoot = cJSON_CreateObject();
104 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
106 jsonDoxm = cJSON_CreateObject();
107 VERIFY_NON_NULL(TAG, jsonDoxm, ERROR);
108 cJSON_AddItemToObject(jsonRoot, OIC_JSON_DOXM_NAME, jsonDoxm );
110 //OxmType -- Not Mandatory
111 if(doxm->oxmTypeLen > 0)
113 cJSON *jsonOxmTyArray = cJSON_CreateArray();
114 VERIFY_NON_NULL(TAG, jsonOxmTyArray, ERROR);
115 cJSON_AddItemToObject (jsonDoxm, OIC_JSON_OXM_TYPE_NAME, jsonOxmTyArray );
116 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
118 cJSON_AddItemToArray (jsonOxmTyArray, cJSON_CreateString(doxm->oxmType[i]));
122 //Oxm -- Not Mandatory
125 cJSON *jsonOxmArray = cJSON_CreateArray();
126 VERIFY_NON_NULL(TAG, jsonOxmArray, ERROR);
127 cJSON_AddItemToObject (jsonDoxm, OIC_JSON_OXM_NAME,jsonOxmArray );
128 for (size_t i = 0; i < doxm->oxmLen; i++)
130 cJSON_AddItemToArray (jsonOxmArray, cJSON_CreateNumber(doxm->oxm[i]));
134 //OxmSel -- Mandatory
135 cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_OXM_SEL_NAME, (int)doxm->oxmSel);
138 cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, (int)doxm->sct);
141 cJSON_AddBoolToObject(jsonDoxm, OIC_JSON_OWNED_NAME, doxm->owned);
143 //TODO: Need more clarification on deviceIDFormat field type.
145 //DeviceIdFormat -- Mandatory
146 cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_DEVICE_ID_FORMAT_NAME, doxm->deviceIDFormat);
149 //DeviceId -- Mandatory
151 b64Ret = b64Encode(doxm->deviceID.id, sizeof(doxm->deviceID.id), base64Buff,
152 sizeof(base64Buff), &outLen);
153 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
154 cJSON_AddStringToObject(jsonDoxm, OIC_JSON_DEVICE_ID_NAME, base64Buff);
158 b64Ret = b64Encode(doxm->owner.id, sizeof(doxm->owner.id), base64Buff,
159 sizeof(base64Buff), &outLen);
160 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
161 cJSON_AddStringToObject(jsonDoxm, OIC_JSON_OWNER_NAME, base64Buff);
163 jsonStr = cJSON_PrintUnformatted(jsonRoot);
168 cJSON_Delete(jsonRoot);
173 OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
181 OCStackResult ret = OC_STACK_ERROR;
182 OicSecDoxm_t *doxm = NULL;
183 cJSON *jsonDoxm = NULL;
184 cJSON *jsonObj = NULL;
186 size_t jsonObjLen = 0;
187 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
189 B64Result b64Ret = B64_OK;
191 cJSON *jsonRoot = cJSON_Parse(jsonStr);
192 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
194 jsonDoxm = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME);
195 VERIFY_NON_NULL(TAG, jsonDoxm, ERROR);
197 doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
198 VERIFY_NON_NULL(TAG, doxm, ERROR);
200 //OxmType -- not Mandatory
201 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_TYPE_NAME);
202 if ((jsonObj) && (cJSON_Array == jsonObj->type))
204 doxm->oxmTypeLen = (size_t)cJSON_GetArraySize(jsonObj);
205 VERIFY_SUCCESS(TAG, doxm->oxmTypeLen > 0, ERROR);
207 doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *));
208 VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR);
210 for (size_t i = 0; i < doxm->oxmTypeLen ; i++)
212 cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i);
213 VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR);
215 jsonObjLen = strlen(jsonOxmTy->valuestring) + 1;
216 doxm->oxmType[i] = (char*)OICMalloc(jsonObjLen);
217 VERIFY_NON_NULL(TAG, doxm->oxmType[i], ERROR);
218 strncpy((char *)doxm->oxmType[i], (char *)jsonOxmTy->valuestring, jsonObjLen);
222 //Oxm -- not Mandatory
223 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_NAME);
224 if (jsonObj && cJSON_Array == jsonObj->type)
226 doxm->oxmLen = (size_t)cJSON_GetArraySize(jsonObj);
227 VERIFY_SUCCESS(TAG, doxm->oxmLen > 0, ERROR);
229 doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(OicSecOxm_t));
230 VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
232 for (size_t i = 0; i < doxm->oxmLen ; i++)
234 cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i);
235 VERIFY_NON_NULL(TAG, jsonOxm, ERROR);
236 doxm->oxm[i] = (OicSecOxm_t)jsonOxm->valueint;
240 //OxmSel -- Mandatory
241 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
244 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
245 doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint;
247 else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
249 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
250 doxm->oxmSel = gDoxm->oxmSel;
254 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME);
257 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
258 doxm->sct = (OicSecCredType_t)jsonObj->valueint;
260 else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
262 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
263 doxm->sct = gDoxm->sct;
267 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
270 VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
271 doxm->owned = jsonObj->valueint;
273 else // PUT/POST JSON may not have owned so set it to the gDomx->owned
275 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
276 doxm->owned = gDoxm->owned;
279 //DeviceId -- Mandatory
280 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVICE_ID_NAME);
283 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
284 if(cJSON_String == jsonObj->type)
286 //Check for empty string, in case DeviceId field has not been set yet
287 if (jsonObj->valuestring[0])
290 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
291 sizeof(base64Buff), &outLen);
292 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->deviceID.id)),
294 memcpy(doxm->deviceID.id, base64Buff, outLen);
298 else // PUT/POST JSON will not have deviceID so set it to the gDoxm->deviceID.id
300 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
301 memcpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
304 //Owner -- will be empty when device status is unowned.
305 jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
306 if(true == doxm->owned)
308 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
312 VERIFY_SUCCESS(TAG, (cJSON_String == jsonObj->type), ERROR);
314 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
315 sizeof(base64Buff), &outLen);
316 VERIFY_SUCCESS(TAG, ((b64Ret == B64_OK) && (outLen <= sizeof(doxm->owner.id))), ERROR);
317 memcpy(doxm->owner.id, base64Buff, outLen);
323 cJSON_Delete(jsonRoot);
324 if (OC_STACK_OK != ret)
326 DeleteDoxmBinData(doxm);
334 * @todo document this function including why code might need to call this.
335 * The current suspicion is that it's not being called as much as it should.
337 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
343 // Convert Doxm data into JSON for update to persistent storage
344 char *jsonStr = BinToDoxmJSON(doxm);
347 cJSON *jsonDoxm = cJSON_Parse(jsonStr);
351 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_DOXM_NAME, jsonDoxm)))
355 cJSON_Delete(jsonDoxm);
362 static bool ValidateQuery(const char * query)
364 // Send doxm resource data if the state of doxm resource
365 // matches with the query parameters.
366 // else send doxm resource data as NULL
367 // TODO Remove this check and rely on Policy Engine
368 // and Provisioning Mode to enforce provisioning-state
369 // access rules. Eventually, the PE and PM code will
370 // not send a request to the /doxm Entity Handler at all
371 // if it should not respond.
372 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
378 bool bOwnedQry = false; // does querystring contains 'owned' query ?
379 bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
380 bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
381 bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
383 OicParseQueryIter_t parseIter = {.attrPos = NULL};
385 ParseQueryIterInit((unsigned char*)query, &parseIter);
387 while(GetNextQuery(&parseIter))
389 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
392 if((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
397 else if((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
404 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
407 OicUuid_t subject = {.id={0}};
408 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
410 B64Result b64Ret = B64_OK;
412 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
413 sizeof(base64Buff), &outLen);
415 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject.id)), ERROR);
416 memcpy(subject.id, base64Buff, outLen);
417 if(0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
419 bDeviceIDMatch = true;
425 return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
428 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
430 char* jsonStr = NULL;
431 OCEntityHandlerResult ehRet = OC_EH_OK;
433 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing GET request");
435 //Checking if Get request is a query.
438 OIC_LOG (DEBUG, TAG, "HandleDoxmGetRequest processing query");
439 if(!ValidateQuery(ehRequest->query))
446 * For GET or Valid Query request return doxm resource json payload.
447 * For non-valid query return NULL json payload.
448 * A device will 'always' have a default Doxm, so BinToDoxmJSON will
449 * return valid doxm resource json.
452 jsonStr = (ehRet == OC_EH_OK) ? BinToDoxmJSON(gDoxm) : NULL;
454 // Send response payload to request originator
455 if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, jsonStr))
457 OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDoxmGetRequest");
465 static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
467 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing PUT request");
468 OCEntityHandlerResult ehRet = OC_EH_ERROR;
469 OicUuid_t emptyOwner = {.id = {0}};
472 * Convert JSON Doxm data into binary. This will also validate
473 * the Doxm data received.
475 OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
479 // Iotivity SRM ONLY supports OIC_JUST_WORKS now
480 if (OIC_JUST_WORKS == newDoxm->oxmSel)
482 if ((false == gDoxm->owned) && (false == newDoxm->owned))
485 * If current state of the device is un-owned, enable
486 * anonymous ECDH cipher in tinyDTLS so that Provisioning
487 * tool can initiate JUST_WORKS ownership transfer process.
489 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
491 OIC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
493 ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
494 #endif //__WITH_DTLS__
500 //Save the owner's UUID to derive owner credential
501 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
503 // OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
504 // //Generating OwnerPSK
505 // OIC_LOG (INFO, TAG, "Doxm EntityHandle generating OwnerPSK");
506 // //Generate new credential for provisioning tool
507 // ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
508 // (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
509 // VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
511 // Update new state in persistent storage
512 if (true == UpdatePersistentStorage(gDoxm))
518 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
523 * Disable anonymous ECDH cipher in tinyDTLS since device is now
526 CAResult_t caRes = CA_STATUS_OK;
527 caRes = CAEnableAnonECDHCipherSuite(false);
528 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
529 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
532 #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
533 CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
534 #endif //__WITH_X509__
535 #endif //__WITH_DTLS__
539 else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
541 if ((false == gDoxm->owned) && (false == newDoxm->owned))
544 * If current state of the device is un-owned, enable
545 * anonymous ECDH cipher in tinyDTLS so that Provisioning
546 * tool can initiate JUST_WORKS ownership transfer process.
548 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
550 gDoxm->oxmSel = newDoxm->oxmSel;
551 //Update new state in persistent storage
552 if((UpdatePersistentStorage(gDoxm) == true))
558 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
563 CAResult_t caRes = CA_STATUS_OK;
565 caRes = CAEnableAnonECDHCipherSuite(false);
566 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
567 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
569 caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
570 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
572 char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
573 if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
575 //Set the device id to derive temporal PSK
576 SetUuidForRandomPinOxm(&gDoxm->deviceID);
579 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
580 * Credential should not be saved into SVR.
581 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
583 caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm);
584 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
589 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
592 #endif //__WITH_DTLS__
597 //Save the owner's UUID to derive owner credential
598 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
600 //Update new state in persistent storage
601 if((UpdatePersistentStorage(gDoxm) == true))
607 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
616 * When current state of the device is un-owned and Provisioning
617 * Tool is attempting to change the state to 'Owned' with a
618 * qualified value for the field 'Owner'
620 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
621 (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
624 // Update new state in persistent storage
625 if (UpdatePersistentStorage(gDoxm))
627 //Update default ACL of security resource to prevent anonymous user access.
628 if(OC_STACK_OK == UpdateDefaultSecProvACL())
634 OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
640 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
647 if(OC_EH_OK != ehRet)
649 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
650 "DOXM will be reverted.");
653 * If some error is occured while ownership transfer,
654 * ownership transfer related resource should be revert back to initial status.
656 RestoreDoxmToInitState();
657 RestorePstatToInitState();
660 //Send payload to request originator
661 if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
663 OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
665 DeleteDoxmBinData(newDoxm);
671 * This internal method is the entity handler for DOXM resources.
673 OCEntityHandlerResult DoxmEntityHandler (OCEntityHandlerFlag flag,
674 OCEntityHandlerRequest * ehRequest,
678 OCEntityHandlerResult ehRet = OC_EH_ERROR;
680 if(NULL == ehRequest)
686 if (flag & OC_REQUEST_FLAG)
688 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
689 switch (ehRequest->method)
692 ehRet = HandleDoxmGetRequest(ehRequest);
696 ehRet = HandleDoxmPutRequest(ehRequest);
701 SendSRMResponse(ehRequest, ehRet, NULL);
710 * This internal method is used to create '/oic/sec/doxm' resource.
712 OCStackResult CreateDoxmResource()
716 ret = OCCreateResource(&gDoxmHandle,
717 OIC_RSRC_TYPE_SEC_DOXM,
722 OC_OBSERVABLE | OC_SECURE | OC_EXPLICIT_DISCOVERABLE);
724 if (OC_STACK_OK != ret)
726 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
727 DeInitDoxmResource();
733 * Checks if DeviceID is generated during provisioning for the new device.
734 * If DeviceID is NULL then generates the new DeviceID.
735 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
738 static OCStackResult CheckDeviceID()
740 OCStackResult ret = OC_STACK_ERROR;
741 bool validId = false;
742 for (uint8_t i = 0; i < UUID_LENGTH; i++)
744 if (gDoxm->deviceID.id[i] != 0)
753 if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
755 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
760 if (UpdatePersistentStorage(gDoxm))
762 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
763 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
774 * Get the default value.
775 * @retval the gDefaultDoxm pointer;
777 static OicSecDoxm_t* GetDoxmDefault()
779 OIC_LOG (DEBUG, TAG, "GetDoxmToDefault");
780 return &gDefaultDoxm;
784 * This method is used by SRM to retrieve DOXM resource data.
786 * @retval reference to @ref OicSecDoxm_t, binary format of Doxm resource data
788 const OicSecDoxm_t* GetDoxmResourceData()
794 * Initialize DOXM resource by loading data from persistent storage.
796 * @retval OC_STACK_OK for Success, otherwise some error value
798 OCStackResult InitDoxmResource()
800 OCStackResult ret = OC_STACK_ERROR;
802 //Read DOXM resource from PS
803 char* jsonSVRDatabase = GetSVRDatabase();
806 //Convert JSON DOXM into binary format
807 gDoxm = JSONToDoxmBin(jsonSVRDatabase);
810 * If SVR database in persistent storage got corrupted or
811 * is not available for some reason, a default doxm is created
812 * which allows user to initiate doxm provisioning again.
814 if(!jsonSVRDatabase || !gDoxm)
816 gDoxm = GetDoxmDefault();
819 //In case of the server is shut down unintentionally, we should initialize the owner
820 if(false == gDoxm->owned)
822 OicUuid_t emptyUuid = {.id={0}};
823 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
826 ret = CheckDeviceID();
827 if (ret == OC_STACK_OK)
829 //Instantiate 'oic.sec.doxm'
830 ret = CreateDoxmResource();
834 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
836 OICFree(jsonSVRDatabase);
841 * Perform cleanup for DOXM resources.
844 * OC_STACK_OK - no error
845 * OC_STACK_ERROR - stack process error
848 OCStackResult DeInitDoxmResource()
850 OCStackResult ret = OCDeleteResource(gDoxmHandle);
851 if(gDoxm != &gDefaultDoxm)
853 DeleteDoxmBinData(gDoxm);
857 if(OC_STACK_OK == ret)
863 return OC_STACK_ERROR;
869 * This method returns the SRM device ID for this device.
871 * @retval OC_STACK_OK for Success, otherwise some error value
873 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
875 if(deviceID && gDoxm)
877 *deviceID = gDoxm->deviceID;
880 return OC_STACK_ERROR;
884 * @brief Gets the OicUuid_t value for the owner of this device.
886 * @return OC_STACK_OK if devOwner is a valid UUID, otherwise OC_STACK_ERROR.
888 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devOwner)
890 OCStackResult retVal = OC_STACK_ERROR;
894 *devOwner = gDoxm->owner; // TODO change to devOwner when available
895 retVal = OC_STACK_OK;
902 * Function to restore doxm resurce to initial status.
903 * This function will use in case of error while ownership transfer
905 void RestoreDoxmToInitState()
909 OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
911 OicUuid_t emptyUuid = {.id={0}};
912 memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
913 gDoxm->owned = false;
914 gDoxm->oxmSel = OIC_JUST_WORKS;
916 if(!UpdatePersistentStorage(gDoxm))
918 OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");