Multiple Ownership Transfer support.
[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 "iotivity_config.h"
21 #include <stdlib.h>
22 #include <string.h>
23
24 #ifdef HAVE_STRINGS_H
25 #include <strings.h>
26 #endif
27
28 #ifdef __WITH_DTLS__
29 #include "global.h"
30 #endif
31
32 #include "ocstack.h"
33 #include "oic_malloc.h"
34 #include "payload_logging.h"
35 #include "utlist.h"
36 #include "ocrandom.h"
37 #include "ocpayload.h"
38 #include "cainterface.h"
39 #include "ocserverrequest.h"
40 #include "resourcemanager.h"
41 #include "doxmresource.h"
42 #include "pstatresource.h"
43 #include "aclresource.h"
44 #include "amaclresource.h"
45 #include "pconfresource.h"
46 #include "dpairingresource.h"
47 #include "psinterface.h"
48 #include "srmresourcestrings.h"
49 #include "securevirtualresourcetypes.h"
50 #include "credresource.h"
51 #include "srmutility.h"
52 #include "pinoxmcommon.h"
53
54 #define TAG  "SRM-DOXM"
55 #define CHAR_ZERO ('0')
56
57 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
58  * The value of payload size is increased until reaching belox max cbor size. */
59 static const uint16_t CBOR_SIZE = 512;
60
61 /** Max cbor size payload. */
62 static const uint16_t CBOR_MAX_SIZE = 4400;
63
64 static OicSecDoxm_t        *gDoxm = NULL;
65 static OCResourceHandle    gDoxmHandle = NULL;
66
67 static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
68 static OicSecDoxm_t gDefaultDoxm =
69 {
70     NULL,                   /* OicUrn_t *oxmType */
71     0,                      /* size_t oxmTypeLen */
72     &gOicSecDoxmJustWorks,  /* uint16_t *oxm */
73     1,                      /* size_t oxmLen */
74     OIC_JUST_WORKS,         /* uint16_t oxmSel */
75     SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
76     false,                  /* bool owned */
77     {.id = {0}},            /* OicUuid_t deviceID */
78     false,                  /* bool dpc */
79     {.id = {0}},            /* OicUuid_t owner */
80 #ifdef _ENABLE_MULTIPLE_OWNER_
81     NULL,                   /* OicSecSubOwner_t sub-owner list */
82     NULL,                   /* OicSecMomType_t multiple owner mode */
83 #endif //_ENABLE_MULTIPLE_OWNER_
84     {.id = {0}},            /* OicUuid_t rownerID */
85 };
86
87 /**
88  * This method is internal method.
89  * the param roParsed is optionally used to know whether cborPayload has
90  * at least read only property value or not.
91  */
92 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
93                                 OicSecDoxm_t **doxm, bool *roParsed);
94
95 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
96 {
97     if (doxm)
98     {
99         //Clean oxmType
100         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
101         {
102             OICFree(doxm->oxmType[i]);
103         }
104         OICFree(doxm->oxmType);
105
106         //clean oxm
107         OICFree(doxm->oxm);
108
109 #ifdef _ENABLE_MULTIPLE_OWNER_
110         //clean mom
111         OICFree(doxm->mom);
112
113         //clean sub-owner list
114         if(NULL != doxm->subOwners)
115         {
116             OicSecSubOwner_t* subowner = NULL;
117             OicSecSubOwner_t* temp = NULL;
118             LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
119             {
120                 LL_DELETE(doxm->subOwners, subowner);
121                 OICFree(subowner);
122             }
123         }
124 #endif //_ENABLE_MULTIPLE_OWNER_
125
126         //Clean doxm itself
127         OICFree(doxm);
128     }
129 }
130
131 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
132                                 bool rwOnly)
133 {
134     if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
135     {
136         return OC_STACK_INVALID_PARAM;
137     }
138     size_t cborLen = *size;
139     if (0 == cborLen)
140     {
141         cborLen = CBOR_SIZE;
142     }
143     *payload = NULL;
144     *size = 0;
145
146     OCStackResult ret = OC_STACK_ERROR;
147
148     CborEncoder encoder;
149     CborEncoder doxmMap;
150     char* strUuid = NULL;
151
152     int64_t cborEncoderResult = CborNoError;
153
154     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
155     VERIFY_NON_NULL(TAG, outPayload, ERROR);
156     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
157
158     cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
159     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
160
161     //OxmType -- Not Mandatory
162     if (doxm->oxmTypeLen > 0)
163     {
164         CborEncoder oxmType;
165         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
166             strlen(OIC_JSON_OXM_TYPE_NAME));
167         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
168         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
169         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
170
171         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
172         {
173             cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
174                 strlen(doxm->oxmType[i]));
175             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
176         }
177         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
178         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
179     }
180
181     //Oxm -- Not Mandatory
182     if (doxm->oxmLen > 0 && false == rwOnly)
183     {
184         CborEncoder oxm;
185         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
186             strlen(OIC_JSON_OXMS_NAME));
187         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
188         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
189         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
190
191         for (size_t i = 0; i < doxm->oxmLen; i++)
192         {
193             cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
194             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
195         }
196         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
197         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
198     }
199
200     //OxmSel -- Mandatory
201     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
202         strlen(OIC_JSON_OXM_SEL_NAME));
203     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
204     cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
205     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
206
207     //sct -- Mandatory
208     if (false == rwOnly)
209     {
210         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
211             strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
212         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
213         cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
214         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
215     }
216
217     //Owned -- Mandatory
218     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
219         strlen(OIC_JSON_OWNED_NAME));
220     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
221     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
222     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
223
224     if (false == rwOnly)
225     {
226         //DeviceId -- Mandatory
227         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
228             strlen(OIC_JSON_DEVICE_ID_NAME));
229         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
230         ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
231         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
232         cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
233         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
234         OICFree(strUuid);
235         strUuid = NULL;
236     }
237
238 #ifdef _ENABLE_MULTIPLE_OWNER_
239     //Device SubOwnerID -- Not Mandatory
240     if(doxm->subOwners)
241     {
242         size_t subOwnerLen = 0;
243         OicSecSubOwner_t* subOwner = NULL;
244         LL_FOREACH(doxm->subOwners, subOwner)
245         {
246             subOwnerLen++;
247         }
248
249         CborEncoder subOwners;
250         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
251             strlen(OIC_JSON_SUBOWNERID_NAME));
252         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
253         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
254         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
255
256         subOwner = NULL;
257         LL_FOREACH(doxm->subOwners, subOwner)
258         {
259             char* strUuid = NULL;
260             ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
261             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
262             cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
263             OICFree(strUuid);
264             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
265         }
266         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
267         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
268     }
269
270     //Multiple Owner Mode -- Not Mandatory
271     if(doxm->mom)
272     {
273         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
274             strlen(OIC_JSON_MOM_NAME));
275         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
276         cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
277         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
278     }
279 #endif //_ENABLE_MULTIPLE_OWNER_
280
281     //devownerid -- Mandatory
282     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
283         strlen(OIC_JSON_DEVOWNERID_NAME));
284     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
285     ret = ConvertUuidToStr(&doxm->owner, &strUuid);
286     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
287     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
288     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
289     OICFree(strUuid);
290     strUuid = NULL;
291
292     //ROwner -- Mandatory
293     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
294         strlen(OIC_JSON_ROWNERID_NAME));
295     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
296     ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
297     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
298     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
299     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
300     OICFree(strUuid);
301     strUuid = NULL;
302
303     //x.org.iotivity.dpc -- not Mandatory(vendor-specific), but this type is boolean, so instance always has a value.
304     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DPC_NAME,
305         strlen(OIC_JSON_DPC_NAME));
306     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Tag.");
307     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->dpc);
308     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Value.");
309
310     //RT -- Mandatory
311     CborEncoder rtArray;
312     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
313             strlen(OIC_JSON_RT_NAME));
314     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
315     cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
316     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
317     for (size_t i = 0; i < 1; i++)
318     {
319         cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
320                 strlen(OIC_RSRC_TYPE_SEC_DOXM));
321         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
322     }
323     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
324     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
325
326     //IF-- Mandatory
327      CborEncoder ifArray;
328      cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
329              strlen(OIC_JSON_IF_NAME));
330      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
331      cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
332      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
333     for (size_t i = 0; i < 1; i++)
334     {
335         cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
336                 strlen(OC_RSRVD_INTERFACE_DEFAULT));
337         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
338     }
339     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
340     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
341
342     cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
343     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
344
345     if (CborNoError == cborEncoderResult)
346     {
347         *size = encoder.ptr - outPayload;
348         *payload = outPayload;
349         ret = OC_STACK_OK;
350     }
351 exit:
352     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
353     {
354         OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
355         // reallocate and try again!
356         OICFree(outPayload);
357         // Since the allocated initial memory failed, double the memory.
358         cborLen += encoder.ptr - encoder.end;
359         OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
360         cborEncoderResult = CborNoError;
361         ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
362         *size = cborLen;
363     }
364
365     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
366     {
367        OICFree(outPayload);
368        outPayload = NULL;
369        *payload = NULL;
370        *size = 0;
371        ret = OC_STACK_ERROR;
372     }
373
374     return ret;
375 }
376
377 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
378                                 OicSecDoxm_t **secDoxm)
379 {
380     return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
381 }
382
383 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
384                                 OicSecDoxm_t **secDoxm, bool *roParsed)
385 {
386     if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
387     {
388         return OC_STACK_INVALID_PARAM;
389     }
390
391     OCStackResult ret = OC_STACK_ERROR;
392     *secDoxm = NULL;
393
394     CborParser parser;
395     CborError cborFindResult = CborNoError;
396     char* strUuid = NULL;
397     size_t len = 0;
398     CborValue doxmCbor;
399
400     cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
401     CborValue doxmMap;
402     OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
403     VERIFY_NON_NULL(TAG, doxm, ERROR);
404
405     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
406     //OxmType -- not Mandatory
407     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
408     {
409         CborValue oxmType;
410
411         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
412         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
413         VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
414
415         doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
416         VERIFY_NON_NULL(TAG, doxm->oxmType, ERROR);
417
418         cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
419         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
420
421         int i = 0;
422         size_t len = 0;
423         while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
424         {
425             cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
426                                                         &len, NULL);
427             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
428             cborFindResult = cbor_value_advance(&oxmType);
429             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
430         }
431     }
432
433     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
434     //Oxm -- not Mandatory
435     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
436     {
437         CborValue oxm;
438         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
439         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
440         VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
441
442         doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
443         VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
444
445         cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
446         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
447
448         int i = 0;
449         while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
450         {
451             int tmp;
452
453             cborFindResult = cbor_value_get_int(&oxm, &tmp);
454             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
455             doxm->oxm[i++] = (OicSecOxm_t)tmp;
456             cborFindResult = cbor_value_advance(&oxm);
457             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
458         }
459
460         if (roParsed)
461         {
462             *roParsed = true;
463         }
464     }
465     else
466     {
467         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
468         doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
469         VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
470         doxm->oxmLen = gDoxm->oxmLen;
471         for (size_t i = 0; i < gDoxm->oxmLen; i++)
472         {
473             doxm->oxm[i] = gDoxm->oxm[i];
474         }
475     }
476
477     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
478     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
479     {
480         int oxmSel;
481
482         cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
483         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
484         doxm->oxmSel = (OicSecOxm_t)oxmSel;
485     }
486     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
487     {
488         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
489         doxm->oxmSel = gDoxm->oxmSel;
490     }
491
492     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
493     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
494     {
495         int sct;
496
497         cborFindResult = cbor_value_get_int(&doxmMap, &sct);
498         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
499         doxm->sct = (OicSecCredType_t)sct;
500
501         if (roParsed)
502         {
503             *roParsed = true;
504         }
505     }
506     else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
507     {
508         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
509         doxm->sct = gDoxm->sct;
510     }
511
512     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
513     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
514     {
515         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
516         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
517     }
518     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
519     {
520         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
521         doxm->owned = gDoxm->owned;
522     }
523
524     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DPC_NAME, &doxmMap);
525     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
526     {
527         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->dpc);
528         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DPC Value.")
529     }
530     else // PUT/POST JSON may not have dpc so set it to the gDomx->dpc
531     {
532         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
533         doxm->dpc = gDoxm->dpc;
534     }
535
536     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
537     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
538     {
539         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
540         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
541         ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
542         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
543         OICFree(strUuid);
544         strUuid  = NULL;
545
546         if (roParsed)
547         {
548             *roParsed = true;
549         }
550     }
551     else
552     {
553         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
554         memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
555     }
556
557     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
558     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
559     {
560         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
561         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
562         ret = ConvertStrToUuid(strUuid , &doxm->owner);
563         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
564         OICFree(strUuid);
565         strUuid  = NULL;
566     }
567     else
568     {
569         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
570         memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
571     }
572
573 #ifdef _ENABLE_MULTIPLE_OWNER_
574     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
575     if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
576     {
577         int mode = 0;
578         cborFindResult = cbor_value_get_int(&doxmMap, &mode);
579         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
580         if(NULL == doxm->mom)
581         {
582             doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
583             VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
584         }
585         doxm->mom->mode = (OicSecMomType_t)mode;
586     }
587     else if(NULL != gDoxm && NULL != gDoxm->mom)
588     {
589         // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
590         if(NULL == doxm->mom)
591         {
592             doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
593             VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
594         }
595         doxm->mom->mode = gDoxm->mom->mode;
596     }
597
598     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
599     if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
600     {
601         size_t subOwnerLen = 0;
602         CborValue subOwnerCbor;
603         cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
604         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
605         VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
606
607         cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
608         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
609
610         while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
611         {
612             OCStackResult convertRes = OC_STACK_ERROR;
613             OicSecSubOwner_t* subOwner = NULL;
614             char* strUuid = NULL;
615             size_t uuidLen = 0;
616
617             cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
618             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
619
620             subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
621             VERIFY_NON_NULL(TAG, subOwner, ERROR);
622
623             convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
624             VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
625             subOwner->status = MOT_STATUS_DONE;
626             LL_APPEND(doxm->subOwners, subOwner);
627
628             cborFindResult = cbor_value_advance(&subOwnerCbor);
629             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
630         }
631     }
632     else if(NULL != gDoxm && NULL != gDoxm->subOwners)
633     {
634         // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
635         OicSecSubOwner_t* subOwnerItor = NULL;
636         LL_FOREACH(gDoxm->subOwners, subOwnerItor)
637         {
638             OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
639             VERIFY_NON_NULL(TAG, subOwnerId, ERROR);
640
641             memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
642             subOwnerId->status = MOT_STATUS_DONE;
643
644             LL_APPEND(doxm->subOwners, subOwnerId);
645         }
646     }
647 #endif //_ENABLE_MULTIPLE_OWNER_
648
649     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
650     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
651     {
652         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
653         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
654         ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
655         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
656         OICFree(strUuid);
657         strUuid  = NULL;
658     }
659     else
660     {
661         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
662         memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
663     }
664
665     *secDoxm = doxm;
666     ret = OC_STACK_OK;
667
668 exit:
669     if (CborNoError != cborFindResult)
670     {
671         OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
672         DeleteDoxmBinData(doxm);
673         doxm = NULL;
674         *secDoxm = NULL;
675         ret = OC_STACK_ERROR;
676     }
677     return ret;
678 }
679
680 /**
681  * @todo document this function including why code might need to call this.
682  * The current suspicion is that it's not being called as much as it should.
683  */
684 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
685 {
686     bool bRet = false;
687
688     if (NULL != doxm)
689     {
690         // Convert Doxm data into CBOR for update to persistent storage
691         uint8_t *payload = NULL;
692         size_t size = 0;
693         OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
694         if (payload && (OC_STACK_OK == res)
695             && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
696         {
697                 bRet = true;
698         }
699         OICFree(payload);
700     }
701     else
702     {
703         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
704         {
705                 bRet = true;
706         }
707     }
708
709     return bRet;
710 }
711
712 static bool ValidateQuery(const char * query)
713 {
714     // Send doxm resource data if the state of doxm resource
715     // matches with the query parameters.
716     // else send doxm resource data as NULL
717     // TODO Remove this check and rely on Policy Engine
718     // and Provisioning Mode to enforce provisioning-state
719     // access rules. Eventually, the PE and PM code will
720     // not send a request to the /doxm Entity Handler at all
721     // if it should not respond.
722     OIC_LOG (DEBUG, TAG, "In ValidateQuery");
723     if(NULL == gDoxm)
724     {
725         return false;
726     }
727
728     bool bOwnedQry = false;         // does querystring contains 'owned' query ?
729     bool bOwnedMatch = false;       // does 'owned' query value matches with doxm.owned status?
730     bool bDeviceIDQry = false;      // does querystring contains 'deviceid' query ?
731     bool bDeviceIDMatch = false;    // does 'deviceid' query matches with doxm.deviceid ?
732     bool bInterfaceQry = false;      // does querystring contains 'if' query ?
733     bool bInterfaceMatch = false;    // does 'if' query matches with oic.if.baseline ?
734 #ifdef _ENABLE_MULTIPLE_OWNER_
735     bool bMotQry = false;         // does querystring contains 'mom' and 'owned' query ?
736     bool bMotMatch = false;       // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
737 #endif //_ENABLE_MULTIPLE_OWNER_
738
739     OicParseQueryIter_t parseIter = {.attrPos = NULL};
740
741     ParseQueryIterInit((unsigned char*)query, &parseIter);
742
743     while (GetNextQuery(&parseIter))
744     {
745         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
746         {
747             bOwnedQry = true;
748             if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
749                     (gDoxm->owned))
750             {
751                 bOwnedMatch = true;
752             }
753             else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
754                     && (!gDoxm->owned))
755             {
756                 bOwnedMatch = true;
757             }
758         }
759
760 #ifdef _ENABLE_MULTIPLE_OWNER_
761         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
762         {
763             bMotQry = true;
764             OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
765             if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
766             {
767                 if(GetNextQuery(&parseIter))
768                 {
769                     if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
770                     {
771                         if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
772                                 (gDoxm->owned))
773                         {
774                             bMotMatch = true;
775                         }
776                     }
777                 }
778             }
779             return bMotMatch;
780         }
781 #endif //_ENABLE_MULTIPLE_OWNER_
782
783         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
784         {
785             bDeviceIDQry = true;
786             OicUuid_t subject = {.id={0}};
787
788             memcpy(subject.id, parseIter.valPos, parseIter.valLen);
789             if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
790             {
791                 bDeviceIDMatch = true;
792             }
793         }
794
795         if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
796         {
797             bInterfaceQry = true;
798             if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
799             {
800                 bInterfaceMatch = true;
801             }
802             return (bInterfaceQry ? bInterfaceMatch: true);
803         }
804     }
805
806 #ifdef _ENABLE_MULTIPLE_OWNER_
807     return ((bOwnedQry ? bOwnedMatch : true) &&
808             (bDeviceIDQry ? bDeviceIDMatch : true) &&
809             (bMotQry ? bMotMatch : true));
810 #else
811     return ((bOwnedQry ? bOwnedMatch : true) &&
812             (bDeviceIDQry ? bDeviceIDMatch : true));
813 #endif //_ENABLE_MULTIPLE_OWNER_
814 }
815
816 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
817 {
818     OCEntityHandlerResult ehRet = OC_EH_OK;
819
820     OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
821
822     //Checking if Get request is a query.
823     if (ehRequest->query)
824     {
825         OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
826         OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
827         if (!ValidateQuery(ehRequest->query))
828         {
829             ehRet = OC_EH_ERROR;
830         }
831     }
832
833     /*
834      * For GET or Valid Query request return doxm resource CBOR payload.
835      * For non-valid query return NULL json payload.
836      * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
837      * return valid doxm resource json.
838      */
839     uint8_t *payload = NULL;
840     size_t size = 0;
841
842     if (ehRet == OC_EH_OK)
843     {
844         if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
845         {
846             OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
847         }
848     }
849
850     OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
851     OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
852
853     // Send response payload to request originator
854     ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
855                    OC_EH_OK : OC_EH_ERROR;
856
857     OICFree(payload);
858
859     return ehRet;
860 }
861
862 static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
863 {
864     if(src && dst)
865    {
866         // update oxmsel
867         dst->oxmSel = src->oxmSel;
868
869         //update owner
870         memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
871
872         //update rowner
873         memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
874
875         //Update owned status
876         if(dst->owned != src->owned)
877         {
878             dst->owned = src->owned;
879         }
880
881         //update oxms
882         if(0 < src->oxmLen)
883         {
884             OicSecOxm_t* tempOxm = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * src->oxmLen);
885             if(NULL != tempOxm)
886             {
887                 for(size_t i = 0; i < src->oxmLen; i++)
888                 {
889                     tempOxm[i] = src->oxm[i];
890                 }
891                 OICFree(dst->oxm);
892
893                 dst->oxm = tempOxm;
894                 dst->oxmLen = src->oxmLen;
895             }
896         }
897
898 #ifdef _ENABLE_MULTIPLE_OWNER_
899         if(src->mom)
900         {
901             OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
902             if(NULL == dst->mom)
903             {
904                 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
905                 if(NULL != dst->mom)
906                 {
907                     dst->mom->mode = src->mom->mode;
908                 }
909             }
910         }
911 #endif //_ENABLE_MULTIPLE_OWNER_
912     }
913 }
914
915 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
916 #ifdef _ENABLE_MULTIPLE_OWNER_
917 /**
918  * Callback function to handle MOT DTLS handshake result.
919  * @param[out]   object           remote device information.
920  * @param[out]   errorInfo        CA Error information.
921  */
922 void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
923                                 const CAErrorInfo_t *errorInfo)
924 {
925     OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
926
927     if(CA_STATUS_OK == errorInfo->result)
928     {
929         const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
930         if(authenticatedSubOwnerInfo)
931         {
932             OicSecSubOwner_t* subOwnerInst = (OicSecSubOwner_t*)OICMalloc(sizeof(OicSecSubOwner_t));
933             if(subOwnerInst)
934             {
935                 OIC_LOG(DEBUG, TAG, "Adding New SubOwner");
936                 memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id, authenticatedSubOwnerInfo->identity.id_length);
937                 LL_APPEND(gDoxm->subOwners, subOwnerInst);
938                 if(!UpdatePersistentStorage(gDoxm))
939                 {
940                     OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
941                 }
942             }
943         }
944     }
945
946     if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
947     {
948         OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
949     }
950
951     OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
952 }
953 #endif //_ENABLE_MULTIPLE_OWNER_
954 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
955
956 static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest * ehRequest)
957 {
958     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
959     OCEntityHandlerResult ehRet = OC_EH_ERROR;
960     OicUuid_t emptyOwner = {.id = {0} };
961     static uint16_t previousMsgId = 0;
962
963     /*
964      * Convert CBOR Doxm data into binary. This will also validate
965      * the Doxm data received.
966      */
967     OicSecDoxm_t *newDoxm = NULL;
968
969     if (ehRequest->payload)
970     {
971         uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
972         size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
973         bool roParsed = false;
974         OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
975         if (newDoxm && OC_STACK_OK == res)
976         {
977             // Check request on RO property
978             if (true == roParsed)
979             {
980                 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
981                 ehRet = OC_EH_NOT_ACCEPTABLE;
982                 goto exit;
983             }
984
985             // in owned state
986             if (true == gDoxm->owned)
987             {
988                 //Update gDoxm based on newDoxm
989                 updateWriteableProperty(newDoxm, gDoxm);
990
991 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
992 #ifdef _ENABLE_MULTIPLE_OWNER_
993                 //handle mom
994                 if(gDoxm->mom)
995                 {
996                     if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
997                     {
998                         CAResult_t caRes = CA_STATUS_FAILED;
999                         if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1000                         {
1001                             caRes = CAEnableAnonECDHCipherSuite(false);
1002                             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1003                             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1004
1005                             caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter);
1006                             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1007                             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1008
1009                             //Set the device id to derive temporal PSK
1010                             SetUuidForPinBasedOxm(&gDoxm->deviceID);
1011                         }
1012                         else
1013                         {
1014                             OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1015                         }
1016
1017                         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1018                     }
1019                     else
1020                     {
1021                         //if MOM is disabled, revert the DTLS handshake callback
1022                         if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1023                         {
1024                             OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1025                         }
1026                     }
1027                 }
1028
1029                 if(newDoxm->subOwners)
1030                 {
1031                     OicSecSubOwner_t* subowner = NULL;
1032                     OicSecSubOwner_t* temp = NULL;
1033
1034                     OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1035
1036                     if(gDoxm->subOwners)
1037                     {
1038                         LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1039                         {
1040                             LL_DELETE(gDoxm->subOwners, subowner);
1041                             OICFree(subowner);
1042                         }
1043                     }
1044
1045                     subowner = NULL;
1046                     temp = NULL;
1047                     LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1048                     {
1049                         LL_DELETE(newDoxm->subOwners, subowner);
1050                         LL_APPEND(gDoxm->subOwners, subowner);
1051                     }
1052                 }
1053 #endif //_ENABLE_MULTIPLE_OWNER_
1054 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1055
1056                 //Update new state in persistent storage
1057                 if (UpdatePersistentStorage(gDoxm) == true)
1058                 {
1059                     ehRet = OC_EH_OK;
1060                 }
1061                 else
1062                 {
1063                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1064                     ehRet = OC_EH_ERROR;
1065                 }
1066                 goto exit;
1067             }
1068
1069             // in unowned state
1070             if ((false == gDoxm->owned) && (false == newDoxm->owned))
1071             {
1072                 if (OIC_JUST_WORKS == newDoxm->oxmSel)
1073                 {
1074                     /*
1075                      * If current state of the device is un-owned, enable
1076                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
1077                      * tool can initiate JUST_WORKS ownership transfer process.
1078                      */
1079                     if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1080                     {
1081                         OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
1082 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1083                         ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1084 #endif // __WITH_DTLS__ or __WITH_TLS__
1085                         goto exit;
1086                     }
1087                     else
1088                     {
1089 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1090                         //Save the owner's UUID to derive owner credential
1091                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1092
1093                         // Update new state in persistent storage
1094                         if (true == UpdatePersistentStorage(gDoxm))
1095                         {
1096                             ehRet = OC_EH_OK;
1097                         }
1098                         else
1099                         {
1100                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1101                             ehRet = OC_EH_ERROR;
1102                         }
1103
1104                         /*
1105                          * Disable anonymous ECDH cipher in tinyDTLS since device is now
1106                          * in owned state.
1107                          */
1108                         CAResult_t caRes = CA_STATUS_OK;
1109                         caRes = CAEnableAnonECDHCipherSuite(false);
1110                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1111                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1112
1113 #endif // __WITH_DTLS__ or __WITH_TLS__
1114                     }
1115                 }
1116                 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1117                 {
1118                     /*
1119                      * If current state of the device is un-owned, enable
1120                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
1121                      * tool can initiate JUST_WORKS ownership transfer process.
1122                      */
1123                     if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1124                     {
1125                         gDoxm->oxmSel = newDoxm->oxmSel;
1126                         //Update new state in persistent storage
1127                         if ((UpdatePersistentStorage(gDoxm) == true))
1128                         {
1129                             ehRet = OC_EH_OK;
1130                         }
1131                         else
1132                         {
1133                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1134                             ehRet = OC_EH_ERROR;
1135                         }
1136
1137 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1138                         CAResult_t caRes = CA_STATUS_OK;
1139
1140                         caRes = CAEnableAnonECDHCipherSuite(false);
1141                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1142                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1143
1144                         caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256,
1145                                                     ehRequest->devAddr.adapter);
1146                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1147
1148                         char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
1149                          //TODO ehRequest->messageID for copa over TCP always is null. Find reason why.
1150                         if(ehRequest->devAddr.adapter == OC_ADAPTER_IP && previousMsgId != ehRequest->messageID)
1151                         {
1152                             if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
1153                             {
1154                                 //Set the device id to derive temporal PSK
1155                                 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1156
1157                                 /**
1158                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1159                                  * Credential should not be saved into SVR.
1160                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1161                                  */
1162                                 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1163                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1164                                 ehRet = OC_EH_OK;
1165                             }
1166                             else
1167                             {
1168                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1169                                 ehRet = OC_EH_ERROR;
1170                             }
1171                         }
1172                         else if(previousMsgId != ehRequest->messageID)
1173                         {
1174                             if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
1175                             {
1176                                 //Set the device id to derive temporal PSK
1177                                 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1178
1179                                 /**
1180                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1181                                  * Credential should not be saved into SVR.
1182                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1183                                  */
1184                                 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1185                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1186                                 ehRet = OC_EH_OK;
1187                             }
1188                             else
1189                             {
1190                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1191                                 ehRet = OC_EH_ERROR;
1192                             }
1193
1194                         }
1195 #endif // __WITH_DTLS__ or __WITH_TLS__
1196                     }
1197 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1198                     else
1199                     {
1200                         //Save the owner's UUID to derive owner credential
1201                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1202
1203                         //Update new state in persistent storage
1204                         if (UpdatePersistentStorage(gDoxm) == true)
1205                         {
1206                             ehRet = OC_EH_OK;
1207                         }
1208                         else
1209                         {
1210                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1211                             ehRet = OC_EH_ERROR;
1212                         }
1213                     }
1214 #endif // __WITH_DTLS__ or __WITH_TLS__
1215                 }
1216             }
1217
1218             /*
1219              * When current state of the device is un-owned and Provisioning
1220              * Tool is attempting to change the state to 'Owned' with a
1221              * qualified value for the field 'Owner'
1222              */
1223             if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1224                     (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1225             {
1226                 //Change the SVR's resource owner as owner device.
1227                 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1228                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1229                 {
1230                     ehRet = OC_EH_ERROR;
1231                     goto exit;
1232                 }
1233                 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1234                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1235                 {
1236                     ehRet = OC_EH_ERROR;
1237                     goto exit;
1238                 }
1239                 ownerRes = SetCredRownerId(&gDoxm->owner);
1240                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1241                 {
1242                     ehRet = OC_EH_ERROR;
1243                     goto exit;
1244                 }
1245                 ownerRes = SetPstatRownerId(&gDoxm->owner);
1246                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1247                 {
1248                     ehRet = OC_EH_ERROR;
1249                     goto exit;
1250                 }
1251                 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1252                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1253                 {
1254                     ehRet = OC_EH_ERROR;
1255                     goto exit;
1256                 }
1257                 ownerRes = SetPconfRownerId(&gDoxm->owner);
1258                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1259                 {
1260                     ehRet = OC_EH_ERROR;
1261                     goto exit;
1262                 }
1263
1264                 gDoxm->owned = true;
1265                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1266
1267                 // Update new state in persistent storage
1268                 if (UpdatePersistentStorage(gDoxm))
1269                 {
1270                     //Update default ACE of security resource to prevent anonymous user access.
1271                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
1272                     {
1273                         ehRet = OC_EH_OK;
1274                     }
1275                     else
1276                     {
1277                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1278                         ehRet = OC_EH_ERROR;
1279                     }
1280                 }
1281                 else
1282                 {
1283                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1284                     ehRet = OC_EH_ERROR;
1285                 }
1286             }
1287         }
1288     }
1289
1290 exit:
1291     if(OC_EH_OK != ehRet)
1292     {
1293
1294         /*
1295          * If some error is occured while ownership transfer,
1296          * ownership transfer related resource should be revert back to initial status.
1297         */
1298         if(gDoxm)
1299         {
1300             if(!gDoxm->owned && previousMsgId != ehRequest->messageID)
1301             {
1302                 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
1303                                     "DOXM will be reverted.");
1304                 RestoreDoxmToInitState();
1305                 RestorePstatToInitState();
1306             }
1307         }
1308         else
1309         {
1310             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1311         }
1312     }
1313     else
1314     {
1315         previousMsgId = ehRequest->messageID;
1316     }
1317
1318     //Send payload to request originator
1319     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1320                    OC_EH_OK : OC_EH_ERROR;
1321
1322     DeleteDoxmBinData(newDoxm);
1323
1324     return ehRet;
1325 }
1326
1327 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1328                                         OCEntityHandlerRequest * ehRequest,
1329                                         void* callbackParam)
1330 {
1331     (void)callbackParam;
1332     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1333
1334     if(NULL == ehRequest)
1335     {
1336         return ehRet;
1337     }
1338
1339     if (flag & OC_REQUEST_FLAG)
1340     {
1341         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1342
1343         switch (ehRequest->method)
1344         {
1345             case OC_REST_GET:
1346                 ehRet = HandleDoxmGetRequest(ehRequest);
1347                 break;
1348
1349             case OC_REST_POST:
1350                 ehRet = HandleDoxmPostRequest(ehRequest);
1351                 break;
1352
1353             default:
1354                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1355                                OC_EH_OK : OC_EH_ERROR;
1356                 break;
1357         }
1358     }
1359
1360     return ehRet;
1361 }
1362
1363 OCStackResult CreateDoxmResource()
1364 {
1365     OCStackResult ret = OCCreateResource(&gDoxmHandle,
1366                                          OIC_RSRC_TYPE_SEC_DOXM,
1367                                          OC_RSRVD_INTERFACE_DEFAULT,
1368                                          OIC_RSRC_DOXM_URI,
1369                                          DoxmEntityHandler,
1370                                          NULL,
1371                                          OC_SECURE |
1372                                          OC_DISCOVERABLE);
1373
1374     if (OC_STACK_OK != ret)
1375     {
1376         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1377         DeInitDoxmResource();
1378     }
1379     return ret;
1380 }
1381
1382 /**
1383  * Checks if DeviceID is generated during provisioning for the new device.
1384  * If DeviceID is NULL then generates the new DeviceID.
1385  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1386  */
1387 static OCStackResult CheckDeviceID()
1388 {
1389     OCStackResult ret = OC_STACK_ERROR;
1390     bool validId = false;
1391     for (uint8_t i = 0; i < UUID_LENGTH; i++)
1392     {
1393         if (gDoxm->deviceID.id[i] != 0)
1394         {
1395             validId = true;
1396             break;
1397         }
1398     }
1399
1400     if (!validId)
1401     {
1402         if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
1403         {
1404             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1405             return ret;
1406         }
1407         ret = OC_STACK_OK;
1408
1409         if (!UpdatePersistentStorage(gDoxm))
1410         {
1411             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1412             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1413         }
1414     }
1415     else
1416     {
1417         ret = OC_STACK_OK;
1418     }
1419     return ret;
1420 }
1421
1422 /**
1423  * Get the default value.
1424  *
1425  * @return the default value of doxm, @ref OicSecDoxm_t.
1426  */
1427 static OicSecDoxm_t* GetDoxmDefault()
1428 {
1429     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1430     return &gDefaultDoxm;
1431 }
1432
1433 const OicSecDoxm_t* GetDoxmResourceData()
1434 {
1435     return gDoxm;
1436 }
1437
1438 #if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
1439 /**
1440  * Internal API to prepare MOT
1441  */
1442 static void PrepareMOT(const OicSecDoxm_t* doxm)
1443 {
1444     OIC_LOG(INFO, TAG, "IN PrepareMOT");
1445     VERIFY_NON_NULL(TAG, doxm, ERROR);
1446
1447     if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1448     {
1449         CAResult_t caRes = CA_STATUS_FAILED;
1450
1451         OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1452
1453         if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1454         {
1455             caRes = CAEnableAnonECDHCipherSuite(false);
1456             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1457             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1458
1459             caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
1460             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1461 #ifdef __WITH_TLS__
1462             caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_TCP);
1463             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1464 #endif
1465             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1466
1467             //Set the device id to derive temporal PSK
1468             SetUuidForPinBasedOxm(&doxm->deviceID);
1469         }
1470         else
1471         {
1472             OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1473             return;
1474         }
1475
1476         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1477     }
1478
1479     OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1480     return;
1481 exit:
1482     OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1483 }
1484 #endif //defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
1485
1486 OCStackResult InitDoxmResource()
1487 {
1488     OCStackResult ret = OC_STACK_ERROR;
1489
1490     //Read DOXM resource from PS
1491     uint8_t *data = NULL;
1492     size_t size = 0;
1493     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1494     // If database read failed
1495     if (OC_STACK_OK != ret)
1496     {
1497        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1498     }
1499     if (data)
1500     {
1501        // Read DOXM resource from PS
1502        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1503     }
1504     /*
1505      * If SVR database in persistent storage got corrupted or
1506      * is not available for some reason, a default doxm is created
1507      * which allows user to initiate doxm provisioning again.
1508      */
1509      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1510     {
1511         gDoxm = GetDoxmDefault();
1512     }
1513
1514     //In case of the server is shut down unintentionally, we should initialize the owner
1515     if(false == gDoxm->owned)
1516     {
1517         OicUuid_t emptyUuid = {.id={0}};
1518         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1519     }
1520
1521     ret = CheckDeviceID();
1522     if (ret == OC_STACK_OK)
1523     {
1524         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1525         //Instantiate 'oic.sec.doxm'
1526         ret = CreateDoxmResource();
1527     }
1528     else
1529     {
1530         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1531     }
1532     OICFree(data);
1533
1534 #if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
1535     //if MOT is enabled, MOT should be prepared.
1536     if(gDoxm && gDoxm->owned)
1537     {
1538         PrepareMOT(gDoxm);
1539     }
1540 #endif // defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
1541
1542     return ret;
1543 }
1544
1545 OCStackResult DeInitDoxmResource()
1546 {
1547     OCStackResult ret = OCDeleteResource(gDoxmHandle);
1548     if (gDoxm  != &gDefaultDoxm)
1549     {
1550         DeleteDoxmBinData(gDoxm);
1551     }
1552     gDoxm = NULL;
1553
1554     if (OC_STACK_OK == ret)
1555     {
1556         return OC_STACK_OK;
1557     }
1558     else
1559     {
1560         return OC_STACK_ERROR;
1561     }
1562 }
1563
1564 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1565 {
1566     if (deviceID && gDoxm)
1567     {
1568        *deviceID = gDoxm->deviceID;
1569         return OC_STACK_OK;
1570     }
1571     return OC_STACK_ERROR;
1572 }
1573
1574 OCStackResult GetDoxmIsOwned(bool *isOwned)
1575 {
1576     if (isOwned && gDoxm)
1577     {
1578        *isOwned = gDoxm->owned;
1579         return OC_STACK_OK;
1580     }
1581     return OC_STACK_ERROR;
1582 }
1583
1584 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1585 {
1586     bool isPT = false;
1587
1588     if(NULL == deviceID)
1589     {
1590         return OC_STACK_INVALID_PARAM;
1591     }
1592     if(NULL == gDoxm)
1593     {
1594         OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1595         return OC_STACK_NO_RESOURCE;
1596     }
1597
1598     //Check the device's OTM state
1599
1600 #ifdef __WITH_DTLS__
1601     //for normal device.
1602     if(true == gDoxm->owned)
1603     {
1604         OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1605         OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1606         return OC_STACK_ERROR;
1607     }
1608 #endif //__WITH_DTLS
1609
1610     //Save the previous UUID
1611     OicUuid_t tempUuid;
1612     memcpy(tempUuid.id, gDoxm->deviceID.id, sizeof(tempUuid.id));
1613
1614     //Change the UUID
1615     memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1616     if(isPT)
1617     {
1618         memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1619         memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1620     }
1621
1622     //Update PS
1623     if(!UpdatePersistentStorage(gDoxm))
1624     {
1625         //revert UUID in case of update error
1626         memcpy(gDoxm->deviceID.id, tempUuid.id, sizeof(tempUuid.id));
1627         if(isPT)
1628         {
1629             memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
1630             memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
1631         }
1632
1633         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
1634         return OC_STACK_ERROR;
1635     }
1636     return OC_STACK_OK;
1637 }
1638
1639 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1640 {
1641     OCStackResult retVal = OC_STACK_ERROR;
1642     if (gDoxm)
1643     {
1644         OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
1645             gDoxm->owned);
1646         if (gDoxm->owned)
1647         {
1648             *devownerid = gDoxm->owner;
1649             retVal = OC_STACK_OK;
1650         }
1651     }
1652     return retVal;
1653 }
1654
1655 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1656 {
1657     OCStackResult retVal = OC_STACK_ERROR;
1658     if (gDoxm)
1659     {
1660         if( gDoxm->owned )
1661         {
1662             *rowneruuid = gDoxm->rownerID;
1663                     retVal = OC_STACK_OK;
1664         }
1665     }
1666     return retVal;
1667 }
1668
1669 #ifdef _ENABLE_MULTIPLE_OWNER_
1670 /**
1671  * Compare the UUID to SubOwner.
1672  *
1673  * @param[in] uuid device UUID
1674  *
1675  * @return true if context->subjectId exist subowner list, else false.
1676  */
1677 bool IsSubOwner(const OicUuid_t* uuid)
1678 {
1679     bool retVal = false;
1680
1681     if(NULL == uuid)
1682     {
1683         return retVal;
1684     }
1685
1686     if (gDoxm && gDoxm->subOwners)
1687     {
1688         OicSecSubOwner_t* subOwner = NULL;
1689         LL_FOREACH(gDoxm->subOwners, subOwner)
1690         {
1691             if(memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
1692             {
1693                 return true;
1694             }
1695         }
1696     }
1697     return retVal;
1698 }
1699 #endif //_ENABLE_MULTIPLE_OWNER_
1700
1701 /**
1702  * Function to restore doxm resurce to initial status.
1703  * This function will use in case of error while ownership transfer
1704  */
1705 void RestoreDoxmToInitState()
1706 {
1707     if(gDoxm)
1708     {
1709         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
1710
1711         OicUuid_t emptyUuid = {.id={0}};
1712         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
1713         gDoxm->owned = false;
1714         gDoxm->oxmSel = OIC_JUST_WORKS;
1715
1716         if(!UpdatePersistentStorage(gDoxm))
1717         {
1718             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
1719         }
1720     }
1721 }