Update security module according to ocstack update
[platform/upstream/iotivity.git] / resource / csdk / security / src / doxmresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include <stdlib.h>
21 #include <string.h>
22
23 #if HAVE_STRINGS_H
24 #include <strings.h>
25 #endif
26
27 #ifdef __WITH_DTLS__
28 #include "global.h"
29 #endif
30
31 #include "ocstack.h"
32 #include "oic_malloc.h"
33 #include "payload_logging.h"
34 #include "utlist.h"
35 #include "ocrandom.h"
36 #include "ocpayload.h"
37 #include "cainterface.h"
38 #include "ocserverrequest.h"
39 #include "resourcemanager.h"
40 #include "doxmresource.h"
41 #include "pstatresource.h"
42 #include "aclresource.h"
43 #include "amaclresource.h"
44 #include "pconfresource.h"
45 #include "dpairingresource.h"
46 #include "psinterface.h"
47 #include "srmresourcestrings.h"
48 #include "securevirtualresourcetypes.h"
49 #include "credresource.h"
50 #include "srmutility.h"
51 #include "pinoxmcommon.h"
52
53 #define TAG  "SRM-DOXM"
54
55 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
56  * The value of payload size is increased until reaching belox max cbor size. */
57 static const uint16_t CBOR_SIZE = 512;
58
59 /** Max cbor size payload. */
60 static const uint16_t CBOR_MAX_SIZE = 4400;
61
62 /** DOXM Map size - Number of mandatory items. */
63 static const uint8_t DOXM_MAP_SIZE = 9;
64
65 static OicSecDoxm_t        *gDoxm = NULL;
66 static OCResourceHandle    gDoxmHandle = NULL;
67
68 static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
69 static OicSecDoxm_t gDefaultDoxm =
70 {
71     NULL,                   /* OicUrn_t *oxmType */
72     0,                      /* size_t oxmTypeLen */
73     &gOicSecDoxmJustWorks,  /* uint16_t *oxm */
74     1,                      /* size_t oxmLen */
75     OIC_JUST_WORKS,         /* uint16_t oxmSel */
76     SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
77     false,                  /* bool owned */
78     {.id = {0}},            /* OicUuid_t deviceID */
79     false,                  /* bool dpc */
80     {.id = {0}},            /* OicUuid_t owner */
81     {.id = {0}},            /* OicUuid_t rownerID */
82 };
83
84 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
85 {
86     if (doxm)
87     {
88         //Clean oxmType
89         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
90         {
91             OICFree(doxm->oxmType[i]);
92         }
93         OICFree(doxm->oxmType);
94
95         //clean oxm
96         OICFree(doxm->oxm);
97
98         //Clean doxm itself
99         OICFree(doxm);
100     }
101 }
102
103 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size)
104 {
105     if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
106     {
107         return OC_STACK_INVALID_PARAM;
108     }
109     size_t cborLen = *size;
110     if (0 == cborLen)
111     {
112         cborLen = CBOR_SIZE;
113     }
114     *payload = NULL;
115     *size = 0;
116
117     OCStackResult ret = OC_STACK_ERROR;
118
119     CborEncoder encoder;
120     CborEncoder doxmMap;
121     char* strUuid = NULL;
122
123     int64_t cborEncoderResult = CborNoError;
124     uint8_t mapSize = DOXM_MAP_SIZE;
125     if (doxm->oxmTypeLen > 0)
126     {
127         mapSize++;
128     }
129     if (doxm->oxmLen > 0)
130     {
131         mapSize++;
132     }
133
134     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
135     VERIFY_NON_NULL(TAG, outPayload, ERROR);
136     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
137
138     cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, mapSize);
139     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
140
141     //OxmType -- Not Mandatory
142     if (doxm->oxmTypeLen > 0)
143     {
144         CborEncoder oxmType;
145         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
146             strlen(OIC_JSON_OXM_TYPE_NAME));
147         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
148         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
149         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
150
151         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
152         {
153             cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
154                 strlen(doxm->oxmType[i]));
155             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
156         }
157         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
158         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
159     }
160
161     //Oxm -- Not Mandatory
162     if (doxm->oxmLen > 0)
163     {
164         CborEncoder oxm;
165         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
166             strlen(OIC_JSON_OXMS_NAME));
167         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
168         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
169         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
170
171         for (size_t i = 0; i < doxm->oxmLen; i++)
172         {
173             cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
174             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
175         }
176         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
177         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
178     }
179
180     //OxmSel -- Mandatory
181     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
182         strlen(OIC_JSON_OXM_SEL_NAME));
183     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
184     cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
185     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
186
187     //sct -- Mandatory
188     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
189         strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
190     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
191     cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
192     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
193
194     //Owned -- Mandatory
195     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
196         strlen(OIC_JSON_OWNED_NAME));
197     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
198     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
199     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
200
201     //DeviceId -- Mandatory
202     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
203         strlen(OIC_JSON_DEVICE_ID_NAME));
204     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
205     ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
206     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
207     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
208     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
209     OICFree(strUuid);
210     strUuid = NULL;
211
212     //devownerid -- Mandatory
213     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
214         strlen(OIC_JSON_DEVOWNERID_NAME));
215     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
216     ret = ConvertUuidToStr(&doxm->owner, &strUuid);
217     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
218     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
219     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
220     OICFree(strUuid);
221     strUuid = NULL;
222
223     //ROwner -- Mandatory
224     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
225         strlen(OIC_JSON_ROWNERID_NAME));
226     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
227     ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
228     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
229     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
230     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
231     OICFree(strUuid);
232     strUuid = NULL;
233
234     //x.com.samsung.dpc -- not Mandatory(vendor-specific), but this type is boolean, so instance always has a value.
235     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DPC_NAME,
236         strlen(OIC_JSON_DPC_NAME));
237     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Tag.");
238     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->dpc);
239     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Value.");
240
241     //RT -- Mandatory
242     CborEncoder rtArray;
243     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
244             strlen(OIC_JSON_RT_NAME));
245     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
246     cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
247     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
248     for (size_t i = 0; i < 1; i++)
249     {
250         cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
251                 strlen(OIC_RSRC_TYPE_SEC_DOXM));
252         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
253     }
254     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
255     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
256
257     //IF-- Mandatory
258      CborEncoder ifArray;
259      cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
260              strlen(OIC_JSON_IF_NAME));
261      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
262      cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
263      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
264     for (size_t i = 0; i < 1; i++)
265     {
266         cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
267                 strlen(OC_RSRVD_INTERFACE_DEFAULT));
268         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
269     }
270     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
271     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
272
273     cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
274     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
275
276     if (CborNoError == cborEncoderResult)
277     {
278         *size = encoder.ptr - outPayload;
279         *payload = outPayload;
280         ret = OC_STACK_OK;
281     }
282 exit:
283     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
284     {
285         OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
286         // reallocate and try again!
287         OICFree(outPayload);
288         // Since the allocated initial memory failed, double the memory.
289         cborLen += encoder.ptr - encoder.end;
290         OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
291         cborEncoderResult = CborNoError;
292         ret = DoxmToCBORPayload(doxm, payload, &cborLen);
293         *size = cborLen;
294     }
295
296     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
297     {
298        OICFree(outPayload);
299        outPayload = NULL;
300        *payload = NULL;
301        *size = 0;
302        ret = OC_STACK_ERROR;
303     }
304
305     return ret;
306 }
307
308 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
309                                 OicSecDoxm_t **secDoxm)
310 {
311     if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
312     {
313         return OC_STACK_INVALID_PARAM;
314     }
315
316     OCStackResult ret = OC_STACK_ERROR;
317     *secDoxm = NULL;
318
319     CborParser parser;
320     CborError cborFindResult = CborNoError;
321     char* strUuid = NULL;
322     size_t len = 0;
323     CborValue doxmCbor;
324
325     cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
326     CborValue doxmMap;
327     OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
328     VERIFY_NON_NULL(TAG, doxm, ERROR);
329
330     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
331     //OxmType -- not Mandatory
332     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
333     {
334         CborValue oxmType;
335
336         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
337         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.")
338         VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
339
340         doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
341         VERIFY_NON_NULL(TAG, doxm->oxmType, ERROR);
342
343         cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
344         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
345
346         int i = 0;
347         size_t len = 0;
348         while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
349         {
350             cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
351                                                         &len, NULL);
352             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.")
353             cborFindResult = cbor_value_advance(&oxmType);
354             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.")
355         }
356     }
357
358     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
359     //Oxm -- not Mandatory
360     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
361     {
362         CborValue oxm;
363         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
364         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.")
365         VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
366
367         doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
368         VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
369
370         cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
371         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
372
373         int i = 0;
374         while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
375         {
376             cborFindResult = cbor_value_get_int(&oxm, (int *) &doxm->oxm[i++]);
377             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
378             cborFindResult = cbor_value_advance(&oxm);
379             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
380         }
381     }
382
383     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
384     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
385     {
386         cborFindResult = cbor_value_get_int(&doxmMap, (int *) &doxm->oxmSel);
387         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
388     }
389     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
390     {
391         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
392         doxm->oxmSel = gDoxm->oxmSel;
393     }
394
395     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
396     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
397     {
398         cborFindResult = cbor_value_get_int(&doxmMap, (int *) &doxm->sct);
399         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
400     }
401     else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
402     {
403         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
404         doxm->sct = gDoxm->sct;
405     }
406
407     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
408     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
409     {
410         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
411         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
412     }
413     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
414     {
415         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
416         doxm->owned = gDoxm->owned;
417     }
418
419     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DPC_NAME, &doxmMap);
420     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
421     {
422         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->dpc);
423         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DPC Value.")
424     }
425     else // PUT/POST JSON may not have dpc so set it to the gDomx->dpc
426     {
427         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
428         doxm->dpc = gDoxm->dpc;
429     }
430
431     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
432     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
433     {
434         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
435         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
436         ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
437         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
438         OICFree(strUuid);
439         strUuid  = NULL;
440     }
441
442     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
443     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
444     {
445         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
446         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
447         ret = ConvertStrToUuid(strUuid , &doxm->owner);
448         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
449         OICFree(strUuid);
450         strUuid  = NULL;
451     }
452
453     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
454     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
455     {
456         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
457         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
458         ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
459         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
460         OICFree(strUuid);
461         strUuid  = NULL;
462     }
463
464     *secDoxm = doxm;
465     ret = OC_STACK_OK;
466
467 exit:
468     if (CborNoError != cborFindResult)
469     {
470         OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
471         DeleteDoxmBinData(doxm);
472         doxm = NULL;
473         *secDoxm = NULL;
474         ret = OC_STACK_ERROR;
475     }
476     return ret;
477 }
478
479 /**
480  * @todo document this function including why code might need to call this.
481  * The current suspicion is that it's not being called as much as it should.
482  */
483 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
484 {
485     bool bRet = false;
486
487     if (NULL != doxm)
488     {
489         // Convert Doxm data into CBOR for update to persistent storage
490         uint8_t *payload = NULL;
491         size_t size = 0;
492         OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size);
493         if (payload && (OC_STACK_OK == res)
494             && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
495         {
496                 bRet = true;
497         }
498         OICFree(payload);
499     }
500     else
501     {
502         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
503         {
504                 bRet = true;
505         }
506     }
507
508     return bRet;
509 }
510
511 static bool ValidateQuery(const char * query)
512 {
513     // Send doxm resource data if the state of doxm resource
514     // matches with the query parameters.
515     // else send doxm resource data as NULL
516     // TODO Remove this check and rely on Policy Engine
517     // and Provisioning Mode to enforce provisioning-state
518     // access rules. Eventually, the PE and PM code will
519     // not send a request to the /doxm Entity Handler at all
520     // if it should not respond.
521     OIC_LOG (DEBUG, TAG, "In ValidateQuery");
522     if(NULL == gDoxm)
523     {
524         return false;
525     }
526
527     bool bOwnedQry = false;         // does querystring contains 'owned' query ?
528     bool bOwnedMatch = false;       // does 'owned' query value matches with doxm.owned status?
529     bool bDeviceIDQry = false;      // does querystring contains 'deviceid' query ?
530     bool bDeviceIDMatch = false;    // does 'deviceid' query matches with doxm.deviceid ?
531     bool bInterfaceQry = false;      // does querystring contains 'if' query ?
532     bool bInterfaceMatch = false;    // does 'if' query matches with oic.if.baseline ?
533
534     OicParseQueryIter_t parseIter = {.attrPos = NULL};
535
536     ParseQueryIterInit((unsigned char*)query, &parseIter);
537
538     while (GetNextQuery(&parseIter))
539     {
540         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
541         {
542             bOwnedQry = true;
543             if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
544                     (gDoxm->owned))
545             {
546                 bOwnedMatch = true;
547             }
548             else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
549                     && (!gDoxm->owned))
550             {
551                 bOwnedMatch = true;
552             }
553         }
554
555         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
556         {
557             bDeviceIDQry = true;
558             OicUuid_t subject = {.id={0}};
559
560             memcpy(subject.id, parseIter.valPos, parseIter.valLen);
561             if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
562             {
563                 bDeviceIDMatch = true;
564             }
565         }
566
567         if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
568         {
569             bInterfaceQry = true;
570             if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
571             {
572                 bInterfaceMatch = true;
573             }
574             return (bInterfaceQry ? bInterfaceMatch: true);
575         }
576     }
577
578     return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
579 }
580
581 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
582 {
583     OCEntityHandlerResult ehRet = OC_EH_OK;
584
585     OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
586
587     //Checking if Get request is a query.
588     if (ehRequest->query)
589     {
590         OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
591         OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
592         if (!ValidateQuery(ehRequest->query))
593         {
594             ehRet = OC_EH_ERROR;
595         }
596     }
597
598     /*
599      * For GET or Valid Query request return doxm resource CBOR payload.
600      * For non-valid query return NULL json payload.
601      * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
602      * return valid doxm resource json.
603      */
604     uint8_t *payload = NULL;
605     size_t size = 0;
606
607     if (ehRet == OC_EH_OK)
608     {
609         if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size))
610         {
611             OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
612         }
613     }
614
615     OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
616     OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
617
618     // Send response payload to request originator
619     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
620     {
621         ehRet = OC_EH_ERROR;
622         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleDoxmGetRequest");
623     }
624
625     OICFree(payload);
626
627     return ehRet;
628 }
629
630 static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest * ehRequest)
631 {
632     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
633     OCEntityHandlerResult ehRet = OC_EH_ERROR;
634     OicUuid_t emptyOwner = {.id = {0} };
635     static uint16_t previousMsgId = 0;
636
637     /*
638      * Convert CBOR Doxm data into binary. This will also validate
639      * the Doxm data received.
640      */
641     OicSecDoxm_t *newDoxm = NULL;
642
643     if (ehRequest->payload)
644     {
645         uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
646         size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
647         OCStackResult res = CBORPayloadToDoxm(payload, size, &newDoxm);
648
649         if (newDoxm && OC_STACK_OK == res)
650         {
651             if (OIC_JUST_WORKS == newDoxm->oxmSel)
652             {
653                 if ((false == gDoxm->owned) && (false == newDoxm->owned))
654                 {
655                     /*
656                      * If current state of the device is un-owned, enable
657                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
658                      * tool can initiate JUST_WORKS ownership transfer process.
659                      */
660                     if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
661                     {
662                         OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
663 #ifdef __WITH_DTLS__
664                         ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
665 #endif //__WITH_DTLS__
666                         goto exit;
667                     }
668                     else
669                     {
670 #ifdef __WITH_DTLS__
671                         //Save the owner's UUID to derive owner credential
672                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
673
674                         // Update new state in persistent storage
675                         if (true == UpdatePersistentStorage(gDoxm))
676                         {
677                             ehRet = OC_EH_OK;
678                         }
679                         else
680                         {
681                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
682                             ehRet = OC_EH_ERROR;
683                         }
684
685                         /*
686                          * Disable anonymous ECDH cipher in tinyDTLS since device is now
687                          * in owned state.
688                          */
689                         CAResult_t caRes = CA_STATUS_OK;
690                         caRes = CAEnableAnonECDHCipherSuite(false);
691                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
692                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
693
694 #ifdef __WITH_X509__
695 #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
696                         CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
697 #endif //__WITH_X509__
698 #endif //__WITH_DTLS__
699                     }
700                 }
701             }
702             else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
703             {
704                 if ((false == gDoxm->owned) && (false == newDoxm->owned))
705                 {
706                     /*
707                      * If current state of the device is un-owned, enable
708                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
709                      * tool can initiate JUST_WORKS ownership transfer process.
710                      */
711                     if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
712                     {
713                         gDoxm->oxmSel = newDoxm->oxmSel;
714                         //Update new state in persistent storage
715                         if ((UpdatePersistentStorage(gDoxm) == true))
716                         {
717                             ehRet = OC_EH_OK;
718                         }
719                         else
720                         {
721                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
722                             ehRet = OC_EH_ERROR;
723                         }
724
725 #ifdef __WITH_DTLS__
726                         CAResult_t caRes = CA_STATUS_OK;
727
728                         caRes = CAEnableAnonECDHCipherSuite(false);
729                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
730                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
731
732                         caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
733                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
734
735                         if(previousMsgId != ehRequest->messageID)
736                         {
737                             char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
738                             if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
739                             {
740                                 //Set the device id to derive temporal PSK
741                                 SetUuidForRandomPinOxm(&gDoxm->deviceID);
742
743                                 /**
744                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
745                                  * Credential should not be saved into SVR.
746                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
747                                  */
748                                 caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm);
749                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
750                                 ehRet = OC_EH_OK;
751                             }
752                             else
753                             {
754                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
755                                 ehRet = OC_EH_ERROR;
756                             }
757                         }
758 #endif //__WITH_DTLS__
759                     }
760                     else
761                     {
762 #ifdef __WITH_DTLS__
763                         //Save the owner's UUID to derive owner credential
764                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
765
766                         //Update new state in persistent storage
767                         if (UpdatePersistentStorage(gDoxm) == true)
768                         {
769                             ehRet = OC_EH_OK;
770                         }
771                         else
772                         {
773                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
774                             ehRet = OC_EH_ERROR;
775                         }
776 #endif
777                     }
778                 }
779             }
780
781             /*
782              * When current state of the device is un-owned and Provisioning
783              * Tool is attempting to change the state to 'Owned' with a
784              * qualified value for the field 'Owner'
785              */
786             if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
787                     (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
788             {
789                 //Change the SVR's resource owner as owner device.
790                 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
791                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
792                 {
793                     ehRet = OC_EH_ERROR;
794                     goto exit;
795                 }
796                 ownerRes = SetAmaclRownerId(&gDoxm->owner);
797                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
798                 {
799                     ehRet = OC_EH_ERROR;
800                     goto exit;
801                 }
802                 ownerRes = SetCredRownerId(&gDoxm->owner);
803                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
804                 {
805                     ehRet = OC_EH_ERROR;
806                     goto exit;
807                 }
808                 ownerRes = SetPstatRownerId(&gDoxm->owner);
809                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
810                 {
811                     ehRet = OC_EH_ERROR;
812                     goto exit;
813                 }
814                 ownerRes = SetDpairingRownerId(&gDoxm->owner);
815                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
816                 {
817                     ehRet = OC_EH_ERROR;
818                     goto exit;
819                 }
820                 ownerRes = SetPconfRownerId(&gDoxm->owner);
821                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
822                 {
823                     ehRet = OC_EH_ERROR;
824                     goto exit;
825                 }
826
827                 gDoxm->owned = true;
828                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
829
830                 // Update new state in persistent storage
831                 if (UpdatePersistentStorage(gDoxm))
832                 {
833                     //Update default ACE of security resource to prevent anonymous user access.
834                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
835                     {
836                         ehRet = OC_EH_OK;
837                     }
838                     else
839                     {
840                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
841                         ehRet = OC_EH_ERROR;
842                     }
843                 }
844                 else
845                 {
846                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
847                     ehRet = OC_EH_ERROR;
848                 }
849             }
850         }
851     }
852
853 exit:
854     if(OC_EH_OK != ehRet)
855     {
856
857         /*
858          * If some error is occured while ownership transfer,
859          * ownership transfer related resource should be revert back to initial status.
860         */
861         if(gDoxm)
862         {
863             if(!gDoxm->owned && previousMsgId != ehRequest->messageID)
864             {
865                 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
866                                     "DOXM will be reverted.");
867                 RestoreDoxmToInitState();
868                 RestorePstatToInitState();
869             }
870         }
871         else
872         {
873             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
874         }
875     }
876     else
877     {
878         previousMsgId = ehRequest->messageID;
879     }
880
881     //Send payload to request originator
882     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
883     {
884         ehRet = OC_EH_ERROR;
885         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleDoxmPostRequest");
886     }
887     DeleteDoxmBinData(newDoxm);
888
889     return ehRet;
890 }
891
892 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
893                                         OCEntityHandlerRequest * ehRequest,
894                                         void* callbackParam)
895 {
896     (void)callbackParam;
897     OCEntityHandlerResult ehRet = OC_EH_ERROR;
898
899     if(NULL == ehRequest)
900     {
901         return ehRet;
902     }
903
904     if (flag & OC_REQUEST_FLAG)
905     {
906         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
907
908         switch (ehRequest->method)
909         {
910             case OC_REST_GET:
911                 ehRet = HandleDoxmGetRequest(ehRequest);
912                 break;
913
914             case OC_REST_POST:
915                 ehRet = HandleDoxmPostRequest(ehRequest);
916                 break;
917
918             default:
919                 ehRet = OC_EH_ERROR;
920                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
921                 break;
922         }
923     }
924
925     return ehRet;
926 }
927
928 OCStackResult CreateDoxmResource()
929 {
930     OCStackResult ret = OCCreateResource(&gDoxmHandle,
931                                          OIC_RSRC_TYPE_SEC_DOXM,
932                                          OC_RSRVD_INTERFACE_DEFAULT,
933                                          OIC_RSRC_DOXM_URI,
934                                          DoxmEntityHandler,
935                                          NULL,
936                                          OC_SECURE |
937                                          OC_DISCOVERABLE);
938
939     if (OC_STACK_OK != ret)
940     {
941         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
942         DeInitDoxmResource();
943     }
944     return ret;
945 }
946
947 /**
948  * Checks if DeviceID is generated during provisioning for the new device.
949  * If DeviceID is NULL then generates the new DeviceID.
950  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
951  */
952 static OCStackResult CheckDeviceID()
953 {
954     OCStackResult ret = OC_STACK_ERROR;
955     bool validId = false;
956     for (uint8_t i = 0; i < UUID_LENGTH; i++)
957     {
958         if (gDoxm->deviceID.id[i] != 0)
959         {
960             validId = true;
961             break;
962         }
963     }
964
965     if (!validId)
966     {
967         if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
968         {
969             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
970             return ret;
971         }
972         ret = OC_STACK_OK;
973
974         if (!UpdatePersistentStorage(gDoxm))
975         {
976             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
977             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
978         }
979     }
980     else
981     {
982         ret = OC_STACK_OK;
983     }
984     return ret;
985 }
986
987 /**
988  * Get the default value.
989  *
990  * @return the default value of doxm, @ref OicSecDoxm_t.
991  */
992 static OicSecDoxm_t* GetDoxmDefault()
993 {
994     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
995     return &gDefaultDoxm;
996 }
997
998 const OicSecDoxm_t* GetDoxmResourceData()
999 {
1000     return gDoxm;
1001 }
1002
1003 OCStackResult InitDoxmResource()
1004 {
1005     OCStackResult ret = OC_STACK_ERROR;
1006
1007     //Read DOXM resource from PS
1008     uint8_t *data = NULL;
1009     size_t size = 0;
1010     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1011     // If database read failed
1012     if (OC_STACK_OK != ret)
1013     {
1014        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1015     }
1016     if (data)
1017     {
1018        // Read DOXM resource from PS
1019        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1020     }
1021     /*
1022      * If SVR database in persistent storage got corrupted or
1023      * is not available for some reason, a default doxm is created
1024      * which allows user to initiate doxm provisioning again.
1025      */
1026      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1027     {
1028         gDoxm = GetDoxmDefault();
1029     }
1030
1031     //In case of the server is shut down unintentionally, we should initialize the owner
1032     if(false == gDoxm->owned)
1033     {
1034         OicUuid_t emptyUuid = {.id={0}};
1035         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1036     }
1037
1038     ret = CheckDeviceID();
1039     if (ret == OC_STACK_OK)
1040     {
1041         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1042         //Instantiate 'oic.sec.doxm'
1043         ret = CreateDoxmResource();
1044     }
1045     else
1046     {
1047         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1048     }
1049     OICFree(data);
1050     return ret;
1051 }
1052
1053 OCStackResult DeInitDoxmResource()
1054 {
1055     OCStackResult ret = OCDeleteResource(gDoxmHandle);
1056     if (gDoxm  != &gDefaultDoxm)
1057     {
1058         DeleteDoxmBinData(gDoxm);
1059     }
1060     gDoxm = NULL;
1061
1062     if (OC_STACK_OK == ret)
1063     {
1064         return OC_STACK_OK;
1065     }
1066     else
1067     {
1068         return OC_STACK_ERROR;
1069     }
1070 }
1071
1072 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1073 {
1074     if (deviceID && gDoxm)
1075     {
1076        *deviceID = gDoxm->deviceID;
1077         return OC_STACK_OK;
1078     }
1079     return OC_STACK_ERROR;
1080 }
1081
1082 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1083 {
1084     OCStackResult retVal = OC_STACK_ERROR;
1085     if (gDoxm)
1086     {
1087         OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
1088             gDoxm->owned);
1089         if (gDoxm->owned)
1090         {
1091             *devownerid = gDoxm->owner;
1092             retVal = OC_STACK_OK;
1093         }
1094     }
1095     return retVal;
1096 }
1097
1098 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1099 {
1100     OCStackResult retVal = OC_STACK_ERROR;
1101     if (gDoxm)
1102     {
1103         if( gDoxm->owned )
1104         {
1105             *rowneruuid = gDoxm->rownerID;
1106                     retVal = OC_STACK_OK;
1107         }
1108     }
1109     return retVal;
1110 }
1111
1112 /**
1113  * Function to restore doxm resurce to initial status.
1114  * This function will use in case of error while ownership transfer
1115  */
1116 void RestoreDoxmToInitState()
1117 {
1118     if(gDoxm)
1119     {
1120         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
1121
1122         OicUuid_t emptyUuid = {.id={0}};
1123         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
1124         gDoxm->owned = false;
1125         gDoxm->oxmSel = OIC_JUST_WORKS;
1126
1127         if(!UpdatePersistentStorage(gDoxm))
1128         {
1129             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
1130         }
1131     }
1132 }