Resolved svace issues
[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 "iotivity_debug.h"
22 #include <stdlib.h>
23 #include <string.h>
24
25 #ifdef HAVE_STRINGS_H
26 #include <strings.h>
27 #endif
28
29 #include "ocstack.h"
30 #include "oic_malloc.h"
31 #include "payload_logging.h"
32 #include "utlist.h"
33 #include "ocrandom.h"
34 #include "ocpayload.h"
35 #include "ocpayloadcbor.h"
36 #include "cainterface.h"
37 #include "ocserverrequest.h"
38 #include "resourcemanager.h"
39 #include "doxmresource.h"
40 #include "pstatresource.h"
41 #include "aclresource.h"
42 #include "amaclresource.h"
43 #include "pconfresource.h"
44 #include "dpairingresource.h"
45 #include "psinterface.h"
46 #include "srmresourcestrings.h"
47 #include "securevirtualresourcetypes.h"
48 #include "credresource.h"
49 #include "srmutility.h"
50 #include "pinoxmcommon.h"
51 #include "oxmverifycommon.h"
52 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
53 #include <mbedtls/ssl_ciphersuites.h>
54 #include <mbedtls/md.h>
55 #include "pkix_interface.h"
56 #endif
57
58 #define TAG  "OIC_SRM_DOXM"
59 #define CHAR_ZERO ('0')
60
61 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
62  * The value of payload size is increased until reaching belox max cbor size. */
63 static const uint16_t CBOR_SIZE = 512;
64
65 /** Max cbor size payload. */
66 static const uint16_t CBOR_MAX_SIZE = 4400;
67
68 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
69 /** MAX uuid seed size */
70 #define MAX_UUID_SEED_SIZE (64)
71 /** MIN uuid seed size */
72 #define MIN_UUID_SEED_SIZE (8)
73
74 /** Buffer to save the seed of device UUID */
75 static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
76 static size_t gUuidSeedSize = 0;
77 #endif
78
79 static OicSecDoxm_t        *gDoxm = NULL;
80 static OCResourceHandle    gDoxmHandle = NULL;
81
82 static OicSecOxm_t gDoxmDefaultOxm = OIC_RANDOM_DEVICE_PIN;
83 static OicSecDoxm_t gDefaultDoxm =
84 {
85     NULL,                   /* OicUrn_t *oxmType */
86     0,                      /* size_t oxmTypeLen */
87     &gDoxmDefaultOxm,       /* uint16_t *oxm */
88     1,                      /* size_t oxmLen */
89     OIC_RANDOM_DEVICE_PIN,  /* uint16_t oxmSel */
90     SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
91     false,                  /* bool owned */
92     {.id = {0}},            /* OicUuid_t deviceID */
93     false,                  /* bool dpc */
94     {.id = {0}},            /* OicUuid_t owner */
95 #ifdef MULTIPLE_OWNER
96     NULL,                   /* OicSecSubOwner_t sub-owner list */
97     NULL,                   /* OicSecMomType_t multiple owner mode */
98 #endif //MULTIPLE_OWNER
99     {.id = {0}},            /* OicUuid_t rownerID */
100 };
101
102 /**
103  * This method is internal method.
104  * the param roParsed is optionally used to know whether cborPayload has
105  * at least read only property value or not.
106  */
107 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
108                                 OicSecDoxm_t **doxm, bool *roParsed);
109
110 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
111 {
112     if (doxm)
113     {
114         //Clean oxmType
115         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
116         {
117             OICFree(doxm->oxmType[i]);
118         }
119         OICFree(doxm->oxmType);
120
121         //clean oxm
122         OICFree(doxm->oxm);
123
124 #ifdef MULTIPLE_OWNER
125         //clean mom
126         OICFree(doxm->mom);
127
128         //clean sub-owner list
129         if(NULL != doxm->subOwners)
130         {
131             OicSecSubOwner_t* subowner = NULL;
132             OicSecSubOwner_t* temp = NULL;
133             LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
134             {
135                 LL_DELETE(doxm->subOwners, subowner);
136                 OICFree(subowner);
137             }
138         }
139 #endif //MULTIPLE_OWNER
140
141         //Clean doxm itself
142         OICFree(doxm);
143     }
144 }
145
146 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
147                                 bool rwOnly)
148 {
149     if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
150     {
151         return OC_STACK_INVALID_PARAM;
152     }
153     size_t cborLen = *size;
154     if (0 == cborLen)
155     {
156         cborLen = CBOR_SIZE;
157     }
158     *payload = NULL;
159     *size = 0;
160
161     OCStackResult ret = OC_STACK_ERROR;
162
163     CborEncoder encoder;
164     CborEncoder doxmMap;
165     char* strUuid = NULL;
166
167     int64_t cborEncoderResult = CborNoError;
168
169     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
170     VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
171
172     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
173
174     cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
175     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
176
177     //OxmType -- Not Mandatory
178     if (doxm->oxmTypeLen > 0)
179     {
180         CborEncoder oxmType;
181         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
182             strlen(OIC_JSON_OXM_TYPE_NAME));
183         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
184         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
185         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
186
187         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
188         {
189             cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
190                 strlen(doxm->oxmType[i]));
191             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
192         }
193         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
194         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
195     }
196
197     //Oxm -- Not Mandatory
198     if (doxm->oxmLen > 0 && false == rwOnly)
199     {
200         CborEncoder oxm;
201         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
202             strlen(OIC_JSON_OXMS_NAME));
203         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
204         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
205         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
206
207         for (size_t i = 0; i < doxm->oxmLen; i++)
208         {
209             cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
210             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
211         }
212         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
213         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
214     }
215
216     //OxmSel -- Mandatory
217     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
218         strlen(OIC_JSON_OXM_SEL_NAME));
219     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
220     cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
221     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
222
223     //sct -- Mandatory
224     if (false == rwOnly)
225     {
226         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
227             strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
228         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
229         cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
230         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
231     }
232
233     //Owned -- Mandatory
234     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
235         strlen(OIC_JSON_OWNED_NAME));
236     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
237     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
238     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
239
240     if (false == rwOnly)
241     {
242         //DeviceId -- Mandatory
243         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
244             strlen(OIC_JSON_DEVICE_ID_NAME));
245         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
246         ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
247         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
248         cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
249         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
250         OICFree(strUuid);
251         strUuid = NULL;
252     }
253
254 #ifdef MULTIPLE_OWNER
255     //Device SubOwnerID -- Not Mandatory
256     if(doxm->subOwners)
257     {
258         size_t subOwnerLen = 0;
259         OicSecSubOwner_t* subOwner = NULL;
260         LL_FOREACH(doxm->subOwners, subOwner)
261         {
262             subOwnerLen++;
263         }
264
265         CborEncoder subOwners;
266         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
267             strlen(OIC_JSON_SUBOWNERID_NAME));
268         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
269         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
270         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
271
272         subOwner = NULL;
273         LL_FOREACH(doxm->subOwners, subOwner)
274         {
275             char* strSubOwnerUuid = NULL;
276             ret = ConvertUuidToStr(&subOwner->uuid, &strSubOwnerUuid);
277             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
278             cborEncoderResult = cbor_encode_text_string(&subOwners, strSubOwnerUuid, strlen(strSubOwnerUuid));
279             OICFree(strSubOwnerUuid);
280             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
281         }
282         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
283         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
284     }
285
286     //Multiple Owner Mode -- Not Mandatory
287     if(doxm->mom)
288     {
289         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
290             strlen(OIC_JSON_MOM_NAME));
291         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
292         cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
293         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
294     }
295 #endif //MULTIPLE_OWNER
296
297     //devownerid -- Mandatory
298     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
299         strlen(OIC_JSON_DEVOWNERID_NAME));
300     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
301     ret = ConvertUuidToStr(&doxm->owner, &strUuid);
302     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
303     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
304     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
305     OICFree(strUuid);
306     strUuid = NULL;
307
308     //ROwner -- Mandatory
309     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
310         strlen(OIC_JSON_ROWNERID_NAME));
311     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
312     ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
313     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
314     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
315     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
316     OICFree(strUuid);
317     strUuid = NULL;
318
319     //RT -- Mandatory
320     CborEncoder rtArray;
321     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
322             strlen(OIC_JSON_RT_NAME));
323     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
324     cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
325     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
326     for (size_t i = 0; i < 1; i++)
327     {
328         cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
329                 strlen(OIC_RSRC_TYPE_SEC_DOXM));
330         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
331     }
332     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
333     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
334
335     //IF-- Mandatory
336      CborEncoder ifArray;
337      cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
338              strlen(OIC_JSON_IF_NAME));
339      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
340      cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
341      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
342     for (size_t i = 0; i < 1; i++)
343     {
344         cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
345                 strlen(OC_RSRVD_INTERFACE_DEFAULT));
346         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
347     }
348     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
349     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
350
351     cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
352     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
353
354     if (CborNoError == cborEncoderResult)
355     {
356         *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
357         *payload = outPayload;
358         ret = OC_STACK_OK;
359     }
360 exit:
361     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
362     {
363         OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
364         // reallocate and try again!
365         OICFree(outPayload);
366         outPayload = NULL;
367         // Since the allocated initial memory failed, double the memory.
368         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
369         OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
370         cborEncoderResult = CborNoError;
371         ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
372         *size = cborLen;
373     }
374
375     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
376     {
377        OICFree(outPayload);
378        outPayload = NULL;
379        *payload = NULL;
380        *size = 0;
381        ret = OC_STACK_ERROR;
382     }
383
384     return ret;
385 }
386
387 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
388                                 OicSecDoxm_t **secDoxm)
389 {
390     return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
391 }
392
393 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
394                                 OicSecDoxm_t **secDoxm, bool *roParsed)
395 {
396     if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
397     {
398         return OC_STACK_INVALID_PARAM;
399     }
400
401     OCStackResult ret = OC_STACK_ERROR;
402     *secDoxm = NULL;
403
404     CborParser parser;
405     CborError cborFindResult = CborNoError;
406     char* strUuid = NULL;
407     size_t len = 0;
408     CborValue doxmCbor;
409
410     cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
411     CborValue doxmMap;
412     OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
413     VERIFY_NOT_NULL(TAG, doxm, ERROR);
414
415     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
416     //OxmType -- not Mandatory
417     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
418     {
419         CborValue oxmType;
420
421         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
422         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
423         VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
424
425         doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
426         VERIFY_NOT_NULL(TAG, doxm->oxmType, ERROR);
427
428         cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
429         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
430
431         int i = 0;
432         size_t oxmTypeStrlen = 0;
433         while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
434         {
435             cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
436                                                         &oxmTypeStrlen, NULL);
437             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
438             cborFindResult = cbor_value_advance(&oxmType);
439             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
440         }
441     }
442
443     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
444     //Oxm -- not Mandatory
445     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
446     {
447         CborValue oxm;
448         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
449         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
450         VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
451
452         doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
453         VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
454
455         cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
456         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
457
458         int i = 0;
459         while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
460         {
461             int tmp;
462
463             cborFindResult = cbor_value_get_int(&oxm, &tmp);
464             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
465             doxm->oxm[i++] = (OicSecOxm_t)tmp;
466             cborFindResult = cbor_value_advance(&oxm);
467             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
468         }
469
470         if (roParsed)
471         {
472             *roParsed = true;
473         }
474     }
475     else
476     {
477         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
478         doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
479         VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
480         doxm->oxmLen = gDoxm->oxmLen;
481         for (size_t i = 0; i < gDoxm->oxmLen; i++)
482         {
483             doxm->oxm[i] = gDoxm->oxm[i];
484         }
485     }
486
487     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
488     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
489     {
490         int oxmSel;
491
492         cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
493         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
494         doxm->oxmSel = (OicSecOxm_t)oxmSel;
495     }
496     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
497     {
498         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
499         doxm->oxmSel = gDoxm->oxmSel;
500     }
501
502     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
503     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
504     {
505         int sct;
506
507         cborFindResult = cbor_value_get_int(&doxmMap, &sct);
508         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
509         doxm->sct = (OicSecCredType_t)sct;
510
511         if (roParsed)
512         {
513             *roParsed = true;
514         }
515     }
516     else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
517     {
518         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
519         doxm->sct = gDoxm->sct;
520     }
521
522     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
523     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
524     {
525         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
526         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
527     }
528     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
529     {
530         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
531         doxm->owned = gDoxm->owned;
532     }
533
534     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
535     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
536     {
537         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
538         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
539         ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
540         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
541         OICFree(strUuid);
542         strUuid  = NULL;
543     }
544     else
545     {
546         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
547         memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
548     }
549
550     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
551     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
552     {
553         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
554         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
555         ret = ConvertStrToUuid(strUuid , &doxm->owner);
556         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
557         OICFree(strUuid);
558         strUuid  = NULL;
559     }
560     else
561     {
562         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
563         memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
564     }
565
566 #ifdef MULTIPLE_OWNER
567     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
568     if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
569     {
570         int mode = 0;
571         cborFindResult = cbor_value_get_int(&doxmMap, &mode);
572         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
573         if(NULL == doxm->mom)
574         {
575             doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
576             VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
577         }
578         doxm->mom->mode = (OicSecMomType_t)mode;
579     }
580     else if(NULL != gDoxm && NULL != gDoxm->mom)
581     {
582         // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
583         if(NULL == doxm->mom)
584         {
585             doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
586             VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
587         }
588         doxm->mom->mode = gDoxm->mom->mode;
589     }
590
591     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
592     if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
593     {
594         size_t subOwnerLen = 0;
595         CborValue subOwnerCbor;
596         cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
597         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
598         VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
599
600         cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
601         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
602
603         while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
604         {
605             OCStackResult convertRes = OC_STACK_ERROR;
606             OicSecSubOwner_t* subOwner = NULL;
607             char* strSubOwnerUuid = NULL;
608             size_t uuidLen = 0;
609
610             cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strSubOwnerUuid, &uuidLen, NULL);
611             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
612
613             subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
614             VERIFY_NOT_NULL(TAG, subOwner, ERROR);
615
616             convertRes = ConvertStrToUuid(strSubOwnerUuid, &subOwner->uuid);
617             VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
618             subOwner->status = MOT_STATUS_DONE;
619             LL_APPEND(doxm->subOwners, subOwner);
620
621             cborFindResult = cbor_value_advance(&subOwnerCbor);
622             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
623         }
624     }
625     else if(NULL != gDoxm && NULL != gDoxm->subOwners)
626     {
627         // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
628         OicSecSubOwner_t* subOwnerItor = NULL;
629         LL_FOREACH(gDoxm->subOwners, subOwnerItor)
630         {
631             OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
632             VERIFY_NOT_NULL(TAG, subOwnerId, ERROR);
633
634             memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
635             subOwnerId->status = MOT_STATUS_DONE;
636
637             LL_APPEND(doxm->subOwners, subOwnerId);
638         }
639     }
640 #endif //MULTIPLE_OWNER
641
642     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
643     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
644     {
645         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
646         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
647         ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
648         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
649         OICFree(strUuid);
650         strUuid  = NULL;
651     }
652     else
653     {
654         VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
655         memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
656     }
657
658     *secDoxm = doxm;
659     ret = OC_STACK_OK;
660
661 exit:
662     if (CborNoError != cborFindResult)
663     {
664         OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
665         DeleteDoxmBinData(doxm);
666         doxm = NULL;
667         *secDoxm = NULL;
668         ret = OC_STACK_ERROR;
669     }
670     return ret;
671 }
672
673 /**
674  * @todo document this function including why code might need to call this.
675  * The current suspicion is that it's not being called as much as it should.
676  */
677 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
678 {
679     bool bRet = false;
680
681     if (NULL != doxm)
682     {
683         // Convert Doxm data into CBOR for update to persistent storage
684         uint8_t *payload = NULL;
685         size_t size = 0;
686         OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
687         if (payload && (OC_STACK_OK == res)
688             && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
689         {
690                 bRet = true;
691         }
692         OICFree(payload);
693     }
694     else
695     {
696         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
697         {
698                 bRet = true;
699         }
700     }
701
702     return bRet;
703 }
704
705 static bool ValidateQuery(const char * query)
706 {
707     // Send doxm resource data if the state of doxm resource
708     // matches with the query parameters.
709     // else send doxm resource data as NULL
710     // TODO Remove this check and rely on Policy Engine
711     // and Provisioning Mode to enforce provisioning-state
712     // access rules. Eventually, the PE and PM code will
713     // not send a request to the /doxm Entity Handler at all
714     // if it should not respond.
715     OIC_LOG (DEBUG, TAG, "In ValidateQuery");
716     if(NULL == gDoxm)
717     {
718         return false;
719     }
720
721     bool bOwnedQry = false;         // does querystring contains 'owned' query ?
722     bool bOwnedMatch = false;       // does 'owned' query value matches with doxm.owned status?
723     bool bDeviceIDQry = false;      // does querystring contains 'deviceid' query ?
724     bool bDeviceIDMatch = false;    // does 'deviceid' query matches with doxm.deviceid ?
725     bool bInterfaceQry = false;      // does querystring contains 'if' query ?
726     bool bInterfaceMatch = false;    // does 'if' query matches with oic.if.baseline ?
727 #ifdef MULTIPLE_OWNER
728     bool bMotMatch = false;       // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
729 #endif //MULTIPLE_OWNER
730
731     OicParseQueryIter_t parseIter = {.attrPos = NULL};
732
733     ParseQueryIterInit((unsigned char*)query, &parseIter);
734
735     while (GetNextQuery(&parseIter))
736     {
737         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
738         {
739             bOwnedQry = true;
740             if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
741                     (gDoxm->owned))
742             {
743                 bOwnedMatch = true;
744             }
745             else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
746                     && (!gDoxm->owned))
747             {
748                 bOwnedMatch = true;
749             }
750         }
751
752 #ifdef MULTIPLE_OWNER
753         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
754         {
755             OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
756             if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
757             {
758                 if(GetNextQuery(&parseIter))
759                 {
760                     if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
761                     {
762                         if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
763                                 (gDoxm->owned))
764                         {
765                             bMotMatch = true;
766                         }
767                     }
768                 }
769             }
770             return bMotMatch;
771         }
772 #endif //MULTIPLE_OWNER
773
774         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
775         {
776             bDeviceIDQry = true;
777             OicUuid_t subject = {.id={0}};
778
779             memcpy(subject.id, parseIter.valPos, parseIter.valLen);
780             if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
781             {
782                 bDeviceIDMatch = true;
783             }
784         }
785
786         if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
787         {
788             bInterfaceQry = true;
789             if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
790             {
791                 bInterfaceMatch = true;
792             }
793             return (bInterfaceQry ? bInterfaceMatch: true);
794         }
795     }
796
797     return ((bOwnedQry ? bOwnedMatch : true) &&
798             (bDeviceIDQry ? bDeviceIDMatch : true));
799 }
800
801 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
802 {
803     OCEntityHandlerResult ehRet = OC_EH_OK;
804
805     OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
806
807     //Checking if Get request is a query.
808     if (ehRequest->query)
809     {
810         OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
811         OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
812         if (!ValidateQuery(ehRequest->query))
813         {
814             ehRet = OC_EH_ERROR;
815         }
816     }
817
818     /*
819      * For GET or Valid Query request return doxm resource CBOR payload.
820      * For non-valid query return NULL json payload.
821      * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
822      * return valid doxm resource json.
823      */
824     uint8_t *payload = NULL;
825     size_t size = 0;
826
827     if (ehRet == OC_EH_OK)
828     {
829         if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
830         {
831             OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
832         }
833     }
834
835     OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
836     OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
837
838     // Send response payload to request originator
839     ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
840                    OC_EH_OK : OC_EH_ERROR;
841
842     OICFree(payload);
843
844     return ehRet;
845 }
846
847 static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
848 {
849     if(src && dst)
850    {
851         // update oxmsel
852         dst->oxmSel = src->oxmSel;
853
854         //update owner
855         memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
856
857         //update rowner
858         memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
859
860         //update deviceuuid
861         memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
862
863         //Update owned status
864         if(dst->owned != src->owned)
865         {
866             dst->owned = src->owned;
867         }
868
869 #ifdef MULTIPLE_OWNER
870         if(src->mom)
871         {
872             OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
873             if(NULL == dst->mom)
874             {
875                 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
876                 if(NULL != dst->mom)
877                 {
878                     dst->mom->mode = src->mom->mode;
879                 }
880             }
881         }
882 #endif //MULTIPLE_OWNER
883     }
884 }
885
886 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
887 #ifdef MULTIPLE_OWNER
888 /**
889  * Callback function to handle MOT DTLS handshake result.
890  * @param[out]   object           remote device information.
891  * @param[out]   errorInfo        CA Error information.
892  */
893 void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
894                                 const CAErrorInfo_t *errorInfo)
895 {
896     OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
897
898     if(CA_STATUS_OK == errorInfo->result)
899     {
900         const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
901         if(authenticatedSubOwnerInfo)
902         {
903             if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
904                             authenticatedSubOwnerInfo->identity.id_length))
905             {
906                 OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
907                 return;
908             }
909
910             OicSecSubOwner_t* subOwnerInst = NULL;
911             LL_FOREACH(gDoxm->subOwners, subOwnerInst)
912             {
913                 if(0 == memcmp(subOwnerInst->uuid.id,
914                                authenticatedSubOwnerInfo->identity.id,
915                                authenticatedSubOwnerInfo->identity.id_length))
916                 {
917                     break;
918                 }
919             }
920
921             if(NULL == subOwnerInst)
922             {
923                 subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
924                 if(subOwnerInst)
925                 {
926                     char* strUuid = NULL;
927                     memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
928                            authenticatedSubOwnerInfo->identity.id_length);
929                     if(OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
930                     {
931                         OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
932                         return;
933                     }
934                     OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
935                     OICFree(strUuid);
936                     LL_APPEND(gDoxm->subOwners, subOwnerInst);
937                     if(!UpdatePersistentStorage(gDoxm))
938                     {
939                         OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
940                     }
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 //MULTIPLE_OWNER
954 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
955
956 /**
957  * Function to validate oxmsel with oxms.
958  *
959  * @param[in] supportedMethods   Array of supported methods
960  * @param[in] numberOfMethods   number of supported methods
961  * @param[out]  selectedMethod         Selected methods
962  * @return  TRUE on success
963  */
964 static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
965         size_t numberOfMethods, OicSecOxm_t *selectedMethod)
966 {
967     bool isValidOxmsel = false;
968
969     OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
970     if (numberOfMethods == 0 || !supportedMethods)
971     {
972         OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
973         return isValidOxmsel;
974     }
975
976     for (size_t i = 0; i < numberOfMethods; i++)
977     {
978             if (*selectedMethod  == supportedMethods[i])
979             {
980                 isValidOxmsel = true;
981                 break;
982             }
983     }
984     if (!isValidOxmsel)
985     {
986         OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
987         return isValidOxmsel;
988     }
989
990     OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
991
992     return isValidOxmsel;
993 }
994
995 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
996 static void DoxmDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
997 {
998     OIC_LOG_V(DEBUG, TAG, "In %s(%p, %p)", __func__, endpoint, info);
999
1000     if ((NULL != endpoint) && (NULL != info) && (CA_STATUS_OK == info->result))
1001     {
1002         /*
1003          * Allow this OBT endpoint to bypass ACE checks for SVRs, while this
1004          * device is not yet owned.
1005          */
1006         OC_VERIFY(CASetSecureEndpointAttribute(endpoint,
1007             CA_SECURE_ENDPOINT_ATTRIBUTE_ADMINISTRATOR));
1008     }
1009
1010     OIC_LOG_V(DEBUG, TAG, "Out %s(%p, %p)", __func__, endpoint, info);
1011 }
1012
1013 static void RegisterOTMSslHandshakeCallback(CAErrorCallback callback)
1014 {
1015     OC_VERIFY(CA_STATUS_OK == CAregisterSslHandshakeCallback(callback));
1016 }
1017 #endif // __WITH_DTLS__ or __WITH_TLS__
1018
1019 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
1020 {
1021     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
1022     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1023     OicUuid_t emptyOwner = {.id = {0} };
1024     static uint16_t previousMsgId = 0;
1025     bool isDuplicatedMsg = false;
1026
1027     /*
1028      * Convert CBOR Doxm data into binary. This will also validate
1029      * the Doxm data received.
1030      */
1031     OicSecDoxm_t *newDoxm = NULL;
1032
1033     if (ehRequest->payload)
1034     {
1035         uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1036         size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1037         bool roParsed = false;
1038         OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
1039         if (newDoxm && OC_STACK_OK == res)
1040         {
1041             /*
1042              * message ID is supported for CoAP over UDP only according to RFC 7252
1043              * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1044              * In case of other transport adapter, duplicate message check is not required.
1045              */
1046             if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1047                  previousMsgId == ehRequest->messageID)
1048             {
1049                 isDuplicatedMsg = true;
1050             }
1051
1052             // Check request on RO property
1053             if (true == roParsed)
1054             {
1055                 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
1056                 ehRet = OC_EH_NOT_ACCEPTABLE;
1057                 goto exit;
1058             }
1059
1060             // in owned state
1061             if (true == gDoxm->owned)
1062             {
1063                 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1064                 {
1065                     OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1066                     ehRet = OC_EH_NOT_ACCEPTABLE;
1067                     goto exit;
1068                 }
1069                 //Update gDoxm based on newDoxm
1070                 updateWriteableProperty(newDoxm, gDoxm);
1071
1072 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1073 #ifdef MULTIPLE_OWNER
1074                 //handle mom
1075                 if(gDoxm->mom)
1076                 {
1077                     if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1078                     {
1079                         CAResult_t caRes = CA_STATUS_FAILED;
1080                         if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1081                         {
1082                             caRes = CAEnableAnonECDHCipherSuite(false);
1083                             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1084                             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1085
1086                             RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1087                             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, ehRequest->devAddr.adapter);
1088                             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1089                             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1090
1091                             //Set the device id to derive temporal PSK
1092                             SetUuidForPinBasedOxm(&gDoxm->deviceID);
1093                         }
1094                         else
1095                         {
1096                             OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1097                         }
1098
1099                         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1100                     }
1101                     else
1102                     {
1103                         //if MOM is disabled, revert the DTLS handshake callback
1104                         if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1105                         {
1106                             OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1107                         }
1108                     }
1109                 }
1110
1111                 if(newDoxm->subOwners)
1112                 {
1113                     OicSecSubOwner_t* subowner = NULL;
1114                     OicSecSubOwner_t* temp = NULL;
1115
1116                     OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1117
1118                     if(gDoxm->subOwners)
1119                     {
1120                         LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1121                         {
1122                             LL_DELETE(gDoxm->subOwners, subowner);
1123                             OICFree(subowner);
1124                         }
1125                     }
1126
1127                     subowner = NULL;
1128                     temp = NULL;
1129                     LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1130                     {
1131                         LL_DELETE(newDoxm->subOwners, subowner);
1132                         LL_APPEND(gDoxm->subOwners, subowner);
1133                     }
1134                 }
1135 #endif //MULTIPLE_OWNER
1136 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1137
1138                 //Update new state in persistent storage
1139                 if (UpdatePersistentStorage(gDoxm) == true)
1140                 {
1141                     ehRet = OC_EH_OK;
1142                 }
1143                 else
1144                 {
1145                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1146                     ehRet = OC_EH_ERROR;
1147                 }
1148                 goto exit;
1149             }
1150
1151             // in unowned state
1152             if ((false == gDoxm->owned) && (false == newDoxm->owned))
1153             {
1154                 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1155                 {
1156                     OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1157                     ehRet = OC_EH_NOT_ACCEPTABLE;
1158                     goto exit;
1159                 }
1160
1161                 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1162                 {
1163                     /*
1164                      * If current state of the device is un-owned, enable
1165                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
1166                      * tool can initiate JUST_WORKS ownership transfer process.
1167                      */
1168                     if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1169                     {
1170                         gDoxm->oxmSel = newDoxm->oxmSel;
1171                         //Update new state in persistent storage
1172                         if ((UpdatePersistentStorage(gDoxm) == true))
1173                         {
1174                             ehRet = OC_EH_OK;
1175                         }
1176                         else
1177                         {
1178                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1179                             ehRet = OC_EH_ERROR;
1180                             goto exit;
1181                         }
1182 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1183                         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1184                         OIC_LOG(INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
1185                         ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1186 #endif // __WITH_DTLS__ or __WITH_TLS__
1187                         goto exit;
1188                     }
1189                     else
1190                     {
1191 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1192                         //Save the owner's UUID to derive owner credential
1193                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1194
1195                         // Update new state in persistent storage
1196                         if (true == UpdatePersistentStorage(gDoxm))
1197                         {
1198                             ehRet = OC_EH_OK;
1199                         }
1200                         else
1201                         {
1202                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1203                             ehRet = OC_EH_ERROR;
1204                             goto exit;
1205                         }
1206
1207                         /*
1208                          * Disable anonymous ECDH cipher in tinyDTLS since device is now
1209                          * in owned state.
1210                          */
1211                         RegisterOTMSslHandshakeCallback(NULL);
1212                         CAResult_t caRes = CA_STATUS_OK;
1213                         caRes = CAEnableAnonECDHCipherSuite(false);
1214                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1215                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1216
1217                         //In case of Mutual Verified Just-Works, verify mutualVerifNum
1218                         if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1219                             false == isDuplicatedMsg)
1220                         {
1221                             uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1222                             uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1223                             OicUuid_t deviceID = {.id = {0}};
1224
1225                             //Generate mutualVerifNum
1226                             OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1227
1228                             char label[LABEL_LEN] = {0};
1229                             snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1230                             if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1231                             {
1232                                 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1233                                 ehRet = OC_EH_ERROR;
1234                                 goto exit;
1235
1236                             }
1237
1238                             CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1239                                     (uint8_t *)label,
1240                                     strlen(label),
1241                                     gDoxm->owner.id, sizeof(gDoxm->owner.id),
1242                                     gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1243                                     preMutualVerifNum, OWNER_PSK_LENGTH_128);
1244                             if (CA_STATUS_OK != pskRet)
1245                             {
1246                                 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1247                                 ehRet = OC_EH_ERROR;
1248                                 goto exit;
1249
1250                             }
1251
1252                             memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1253                                     sizeof(mutualVerifNum));
1254
1255                             //Wait for user confirmation
1256                             if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1257                             {
1258                                 ehRet = OC_EH_NOT_ACCEPTABLE;
1259                             }
1260                             else
1261                             {
1262                                 ehRet = OC_EH_OK;
1263                             }
1264                         }
1265
1266 #endif // __WITH_DTLS__ or __WITH_TLS__
1267                     }
1268                 }
1269                 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1270                 {
1271                     /*
1272                      * If current state of the device is un-owned, enable
1273                      * ECDHE_PSK cipher so that the Provisioning tool can
1274                      * initiate the ownership transfer.
1275                      */
1276                     if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1277                     {
1278                         gDoxm->oxmSel = newDoxm->oxmSel;
1279                         //Update new state in persistent storage
1280                         if ((UpdatePersistentStorage(gDoxm) == true))
1281                         {
1282                             ehRet = OC_EH_OK;
1283                         }
1284                         else
1285                         {
1286                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1287                             ehRet = OC_EH_ERROR;
1288                         }
1289
1290 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1291                         CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1292                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1293                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1294
1295                         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1296                         caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1297                                                     ehRequest->devAddr.adapter);
1298                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1299
1300                         if (!isDuplicatedMsg)
1301                         {
1302                             char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1303                             if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1304                             {
1305                                 //Set the device id to derive temporal PSK
1306                                 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1307
1308                                 /**
1309                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1310                                  * Credential should not be saved into SVR.
1311                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1312                                  */
1313                                 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1314                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1315                                 ehRet = OC_EH_OK;
1316                             }
1317                             else
1318                             {
1319                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1320                                 ehRet = OC_EH_ERROR;
1321                             }
1322                         }
1323 #endif // __WITH_DTLS__ or __WITH_TLS__
1324                     }
1325 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1326                     else
1327                     {
1328                         //Save the owner's UUID to derive owner credential
1329                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1330
1331                         // In case of random-pin based OTM, close the PIN display if callback is registered.
1332                         if (!isDuplicatedMsg)
1333                         {
1334                             ClosePinDisplay();
1335                         }
1336
1337                         //Update new state in persistent storage
1338                         if (UpdatePersistentStorage(gDoxm) == true)
1339                         {
1340                             ehRet = OC_EH_OK;
1341                         }
1342                         else
1343                         {
1344                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1345                             ehRet = OC_EH_ERROR;
1346                         }
1347                     }
1348 #endif // __WITH_DTLS__ or __WITH_TLS__
1349                 }
1350 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1351                 else if (OIC_MANUFACTURER_CERTIFICATE ==  newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1352                 {
1353                     //In case of Confirm Manufacturer Cert, get user confirmation
1354                     if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1355                         false == isDuplicatedMsg &&
1356                         memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1357                     {
1358                         if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1359                         {
1360                             ehRet = OC_EH_NOT_ACCEPTABLE;
1361                             goto exit;
1362                         }
1363                         else
1364                         {
1365                             ehRet = OC_EH_OK;
1366                         }
1367                     }
1368
1369                     //Save the owner's UUID to derive owner credential
1370                     memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1371                     gDoxm->oxmSel = newDoxm->oxmSel;
1372                     //Update new state in persistent storage
1373                     if (UpdatePersistentStorage(gDoxm))
1374                     {
1375                         ehRet = OC_EH_OK;
1376                     }
1377                     else
1378                     {
1379                         OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1380                         ehRet = OC_EH_ERROR;
1381                     }
1382
1383                     RegisterOTMSslHandshakeCallback(NULL);
1384                     CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1385                     VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1386                     OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1387
1388                     //Unset pre-selected ciphersuite, if any
1389                     caRes = CASelectCipherSuite(0, ehRequest->devAddr.adapter);
1390                     VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1391                     OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
1392
1393                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1394                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1395                 }
1396 #endif // __WITH_DTLS__ or __WITH_TLS__
1397             }
1398
1399             /*
1400              * When current state of the device is un-owned and Provisioning
1401              * Tool is attempting to change the state to 'Owned' with a
1402              * qualified value for the field 'Owner'
1403              */
1404             if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1405                     (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1406             {
1407                 //Change the SVR's resource owner as owner device.
1408                 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1409                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1410                 {
1411                     ehRet = OC_EH_ERROR;
1412                     goto exit;
1413                 }
1414                 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1415                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1416                 {
1417                     ehRet = OC_EH_ERROR;
1418                     goto exit;
1419                 }
1420                 ownerRes = SetCredRownerId(&gDoxm->owner);
1421                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1422                 {
1423                     ehRet = OC_EH_ERROR;
1424                     goto exit;
1425                 }
1426                 ownerRes = SetPstatRownerId(&gDoxm->owner);
1427                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1428                 {
1429                     ehRet = OC_EH_ERROR;
1430                     goto exit;
1431                 }
1432                 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1433                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1434                 {
1435                     ehRet = OC_EH_ERROR;
1436                     goto exit;
1437                 }
1438                 ownerRes = SetPconfRownerId(&gDoxm->owner);
1439                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1440                 {
1441                     ehRet = OC_EH_ERROR;
1442                     goto exit;
1443                 }
1444
1445                 gDoxm->owned = true;
1446                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1447
1448                 // Update new state in persistent storage
1449                 if (UpdatePersistentStorage(gDoxm))
1450                 {
1451                     //Update default ACE of security resource to prevent anonymous user access.
1452                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
1453                     {
1454                         ehRet = OC_EH_OK;
1455                     }
1456                     else
1457                     {
1458                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1459                         ehRet = OC_EH_ERROR;
1460                     }
1461                 }
1462                 else
1463                 {
1464                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1465                     ehRet = OC_EH_ERROR;
1466                 }
1467 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1468                 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1469                                             OIC_CON_MFG_CERT== gDoxm->oxmSel)
1470                 {
1471                     CAregisterPkixInfoHandler(GetPkixInfo);
1472                     CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1473                 }
1474 #endif // __WITH_DTLS__ or __WITH_TLS__
1475             }
1476         }
1477     }
1478
1479 exit:
1480     if(OC_EH_OK != ehRet)
1481     {
1482
1483         /*
1484          * If some error is occured while ownership transfer,
1485          * ownership transfer related resource should be revert back to initial status.
1486         */
1487         if(gDoxm)
1488         {
1489             if(!gDoxm->owned)
1490             {
1491                 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1492
1493                 if (!isDuplicatedMsg)
1494                 {
1495                     RestoreDoxmToInitState();
1496                     RestorePstatToInitState();
1497                     OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1498                 }
1499             }
1500         }
1501         else
1502         {
1503             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1504         }
1505     }
1506     else
1507     {
1508         previousMsgId = ehRequest->messageID;
1509     }
1510
1511     //Send payload to request originator
1512     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1513                    OC_EH_OK : OC_EH_ERROR;
1514
1515     DeleteDoxmBinData(newDoxm);
1516
1517     return ehRet;
1518 }
1519
1520 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1521                                         OCEntityHandlerRequest * ehRequest,
1522                                         void* callbackParam)
1523 {
1524     (void)callbackParam;
1525     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1526
1527     if(NULL == ehRequest)
1528     {
1529         return ehRet;
1530     }
1531
1532     if (flag & OC_REQUEST_FLAG)
1533     {
1534         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1535
1536         switch (ehRequest->method)
1537         {
1538             case OC_REST_GET:
1539                 ehRet = HandleDoxmGetRequest(ehRequest);
1540                 break;
1541
1542             case OC_REST_POST:
1543                 ehRet = HandleDoxmPostRequest(ehRequest);
1544                 break;
1545
1546             default:
1547                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1548                                OC_EH_OK : OC_EH_ERROR;
1549                 break;
1550         }
1551     }
1552
1553     return ehRet;
1554 }
1555
1556 OCStackResult CreateDoxmResource()
1557 {
1558     OCStackResult ret = OCCreateResource(&gDoxmHandle,
1559                                          OIC_RSRC_TYPE_SEC_DOXM,
1560                                          OC_RSRVD_INTERFACE_DEFAULT,
1561                                          OIC_RSRC_DOXM_URI,
1562                                          DoxmEntityHandler,
1563                                          NULL,
1564                                          OC_SECURE |
1565                                          OC_DISCOVERABLE);
1566
1567     if (OC_STACK_OK != ret)
1568     {
1569         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1570         DeInitDoxmResource();
1571     }
1572     return ret;
1573 }
1574
1575 /**
1576  * Checks if DeviceID is generated during provisioning for the new device.
1577  * If DeviceID is NULL then generates the new DeviceID.
1578  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1579  */
1580 static OCStackResult CheckDeviceID()
1581 {
1582     OCStackResult ret = OC_STACK_ERROR;
1583     bool validId = false;
1584
1585     for (uint8_t i = 0; i < UUID_LENGTH; i++)
1586     {
1587         if (gDoxm->deviceID.id[i] != 0)
1588         {
1589             validId = true;
1590             break;
1591         }
1592     }
1593
1594     if (!validId)
1595     {
1596         char* strUuid = NULL;
1597 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1598         //If seed value is exists, generate UUID using seed with SHA256
1599         if (0 != gUuidSeedSize)
1600         {
1601             uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1602             int mbedret = 0;
1603
1604             OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1605             OIC_LOG(DEBUG, TAG, "Seed value : ");
1606             OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1607
1608             mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1609                                  gUuidSeed, gUuidSeedSize, hashVal);
1610             if(0 == mbedret)
1611             {
1612                 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1613                 ret = OC_STACK_OK;
1614             }
1615             else
1616             {
1617                 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1618                 ret = OC_STACK_ERROR;
1619             }
1620         }
1621         else
1622         {
1623             if (!OCGenerateUuid(gDoxm->deviceID.id))
1624             {
1625                 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1626                 ret = OC_STACK_ERROR;
1627             }
1628             else
1629             {
1630                 ret = OC_STACK_OK;
1631             }
1632         }
1633 #else
1634         if (!OCGenerateUuid(gDoxm->deviceID.id))
1635         {
1636             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1637             ret = OC_STACK_ERROR;
1638         }
1639         else
1640         {
1641             ret = OC_STACK_OK;
1642         }
1643 #endif
1644
1645         if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1646         {
1647             OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1648             OICFree(strUuid);
1649         }
1650         else
1651         {
1652             OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1653         }
1654
1655
1656         if (!UpdatePersistentStorage(gDoxm))
1657         {
1658             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1659             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1660         }
1661     }
1662     else
1663     {
1664         ret = OC_STACK_OK;
1665     }
1666
1667     return ret;
1668 }
1669
1670 /**
1671  * Get the default value.
1672  *
1673  * @return the default value of doxm, @ref OicSecDoxm_t.
1674  */
1675 static OicSecDoxm_t* GetDoxmDefault()
1676 {
1677     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1678     return &gDefaultDoxm;
1679 }
1680
1681 const OicSecDoxm_t* GetDoxmResourceData()
1682 {
1683     return gDoxm;
1684 }
1685
1686 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1687 /**
1688  * Internal API to prepare MOT
1689  */
1690 static void PrepareMOT(const OicSecDoxm_t* doxm)
1691 {
1692     OIC_LOG(INFO, TAG, "IN PrepareMOT");
1693     VERIFY_NOT_NULL(TAG, doxm, ERROR);
1694
1695     if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1696     {
1697         CAResult_t caRes = CA_STATUS_FAILED;
1698
1699         OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1700
1701         if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1702         {
1703             caRes = CAEnableAnonECDHCipherSuite(false);
1704             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1705             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1706
1707             RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1708             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
1709             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1710 #ifdef __WITH_TLS__
1711             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
1712             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1713 #endif
1714             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1715
1716             //Set the device id to derive temporal PSK
1717             SetUuidForPinBasedOxm(&doxm->deviceID);
1718         }
1719         else
1720         {
1721             OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1722             return;
1723         }
1724
1725         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1726     }
1727
1728     OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1729     return;
1730 exit:
1731     OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1732 }
1733 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1734
1735 OCStackResult InitDoxmResource()
1736 {
1737     OCStackResult ret = OC_STACK_ERROR;
1738
1739     //Read DOXM resource from PS
1740     uint8_t *data = NULL;
1741     size_t size = 0;
1742     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1743     // If database read failed
1744     if (OC_STACK_OK != ret)
1745     {
1746        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1747     }
1748     if (data)
1749     {
1750        // Read DOXM resource from PS
1751        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1752     }
1753     /*
1754      * If SVR database in persistent storage got corrupted or
1755      * is not available for some reason, a default doxm is created
1756      * which allows user to initiate doxm provisioning again.
1757      */
1758      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1759     {
1760         gDoxm = GetDoxmDefault();
1761     }
1762
1763     //In case of the server is shut down unintentionally, we should initialize the owner
1764     if(gDoxm && (false == gDoxm->owned))
1765     {
1766         OicUuid_t emptyUuid = {.id={0}};
1767         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1768     }
1769
1770     ret = CheckDeviceID();
1771     if (ret == OC_STACK_OK)
1772     {
1773         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1774         //Instantiate 'oic.sec.doxm'
1775         ret = CreateDoxmResource();
1776     }
1777     else
1778     {
1779         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1780     }
1781     OICFree(data);
1782
1783 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1784     //if MOT is enabled, MOT should be prepared.
1785     if(gDoxm && gDoxm->owned)
1786     {
1787         PrepareMOT(gDoxm);
1788     }
1789 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1790
1791     return ret;
1792 }
1793
1794 OCStackResult DeInitDoxmResource()
1795 {
1796     OCStackResult ret = OCDeleteResource(gDoxmHandle);
1797     if (gDoxm  != &gDefaultDoxm)
1798     {
1799         DeleteDoxmBinData(gDoxm);
1800     }
1801     gDoxm = NULL;
1802
1803     if (OC_STACK_OK == ret)
1804     {
1805         return OC_STACK_OK;
1806     }
1807     else
1808     {
1809         return OC_STACK_ERROR;
1810     }
1811 }
1812
1813 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1814 {
1815     if (deviceID && gDoxm)
1816     {
1817        *deviceID = gDoxm->deviceID;
1818         return OC_STACK_OK;
1819     }
1820     return OC_STACK_ERROR;
1821 }
1822
1823 OCStackResult GetDoxmIsOwned(bool *isOwned)
1824 {
1825     if (isOwned && gDoxm)
1826     {
1827        *isOwned = gDoxm->owned;
1828         return OC_STACK_OK;
1829     }
1830     return OC_STACK_ERROR;
1831 }
1832
1833 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1834 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
1835 {
1836     OIC_LOG_V(INFO, TAG, "In %s", __func__);
1837
1838     if (NULL == seed)
1839     {
1840         return OC_STACK_INVALID_PARAM;
1841     }
1842     if (MAX_UUID_SEED_SIZE < seedSize)
1843     {
1844         OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
1845         return OC_STACK_INVALID_PARAM;
1846     }
1847     if (MIN_UUID_SEED_SIZE > seedSize)
1848     {
1849         OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
1850         return OC_STACK_INVALID_PARAM;
1851     }
1852
1853     memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
1854     memcpy(gUuidSeed, seed, seedSize);
1855     gUuidSeedSize = seedSize;
1856
1857     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1858
1859     return OC_STACK_OK;
1860 }
1861 #endif
1862
1863 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1864 {
1865     bool isOwnerUpdated = false;
1866     bool isRownerUpdated = false;
1867     if (NULL == deviceID)
1868     {
1869         return OC_STACK_INVALID_PARAM;
1870     }
1871     if (NULL == gDoxm)
1872     {
1873         OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1874         return OC_STACK_NO_RESOURCE;
1875     }
1876
1877 #ifdef __WITH_DTLS__
1878     //for normal device.
1879     if (true == gDoxm->owned &&
1880         memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
1881     {
1882         OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1883         OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1884         return OC_STACK_ERROR;
1885     }
1886 #endif //__WITH_DTLS
1887
1888     //Save the previous UUID
1889     OicUuid_t prevUuid;
1890     memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
1891
1892     //Change the device UUID
1893     memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1894
1895     //Change the owner ID if necessary
1896     if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
1897     {
1898         memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1899         isOwnerUpdated = true;
1900     }
1901     //Change the resource owner ID if necessary
1902     if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
1903     {
1904         memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1905         isRownerUpdated = true;
1906     }
1907     // TODO: T.B.D Change resource owner for pstat, acl and cred
1908
1909     //Update PS
1910     if (!UpdatePersistentStorage(gDoxm))
1911     {
1912         //revert UUID in case of PSI error
1913         memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(prevUuid.id));
1914         if (isOwnerUpdated)
1915         {
1916             memcpy(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id));
1917         }
1918         if (isRownerUpdated)
1919         {
1920             memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id));
1921         }
1922         // TODO: T.B.D Revert resource owner for pstat, acl and cred
1923
1924         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
1925         return OC_STACK_ERROR;
1926     }
1927     return OC_STACK_OK;
1928 }
1929
1930 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1931 {
1932     OCStackResult retVal = OC_STACK_ERROR;
1933     if (gDoxm)
1934     {
1935         OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
1936             gDoxm->owned);
1937         if (gDoxm->owned)
1938         {
1939             *devownerid = gDoxm->owner;
1940             retVal = OC_STACK_OK;
1941         }
1942     }
1943     return retVal;
1944 }
1945
1946 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1947 {
1948     OCStackResult retVal = OC_STACK_ERROR;
1949     if (gDoxm)
1950     {
1951         if( gDoxm->owned )
1952         {
1953             *rowneruuid = gDoxm->rownerID;
1954                     retVal = OC_STACK_OK;
1955         }
1956     }
1957     return retVal;
1958 }
1959
1960 #ifdef MULTIPLE_OWNER
1961 /**
1962  * Compare the UUID to SubOwner.
1963  *
1964  * @param[in] uuid device UUID
1965  *
1966  * @return true if context->subjectId exist subowner list, else false.
1967  */
1968 bool IsSubOwner(const OicUuid_t* uuid)
1969 {
1970     bool retVal = false;
1971
1972     if (NULL == uuid)
1973     {
1974         return retVal;
1975     }
1976
1977     if (gDoxm && gDoxm->subOwners)
1978     {
1979         if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
1980         {
1981             return false;
1982         }
1983
1984         OicSecSubOwner_t* subOwner = NULL;
1985         LL_FOREACH(gDoxm->subOwners, subOwner)
1986         {
1987             if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
1988             {
1989                 return true;
1990             }
1991         }
1992     }
1993     return retVal;
1994 }
1995 #endif //MULTIPLE_OWNER
1996
1997 /**
1998  * Function to restore doxm resurce to initial status.
1999  * This function will use in case of error while ownership transfer
2000  */
2001 void RestoreDoxmToInitState()
2002 {
2003     if(gDoxm)
2004     {
2005         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
2006
2007         OicUuid_t emptyUuid = {.id={0}};
2008         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
2009         gDoxm->owned = false;
2010         gDoxm->oxmSel = OIC_JUST_WORKS;
2011
2012         if(!UpdatePersistentStorage(gDoxm))
2013         {
2014             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2015         }
2016     }
2017 }
2018
2019 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2020 {
2021     OCStackResult ret = OC_STACK_ERROR;
2022     uint8_t *cborPayload = NULL;
2023     size_t size = 0;
2024
2025     if(NULL == gDoxm)
2026     {
2027         ret = OC_STACK_NO_RESOURCE;
2028         return ret;
2029     }
2030
2031     if( newROwner && (false == gDoxm->owned) )
2032     {
2033         gDoxm->owned = true;
2034         memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2035         memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2036
2037         ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2038         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2039
2040         ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2041         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2042
2043         OICFree(cborPayload);
2044     }
2045
2046     return ret;
2047
2048 exit:
2049     OICFree(cborPayload);
2050     return ret;
2051 }
2052
2053 #ifdef MULTIPLE_OWNER
2054 /** This function checks if two sets of /oic/sec/doxm MOT-specific properties are identical.
2055  *
2056  * @param doxm1 is a pointer to the first @ref OicSecDoxm_t data.
2057  * @param doxm2 is a pointer to the second @ref OicSecDoxm_t data.
2058  *
2059  * @return true if all of the properties are identical, else false.
2060  */
2061 static bool AreDoxmBinMOTPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2062 {
2063     //Compare the subOwners lists.
2064     OicSecSubOwner_t* subOwner1 = doxm1->subOwners;
2065     OicSecSubOwner_t* subOwner2 = doxm2->subOwners;
2066
2067     for (;;)
2068     {
2069         if ((NULL == subOwner1) && (NULL == subOwner2))
2070         {
2071             //Reached the end of both lists, so the two lists were identical.
2072             break;
2073         }
2074
2075         if ((NULL != subOwner1) && (NULL != subOwner2))
2076         {
2077             if (0 != memcmp(&subOwner1->uuid, &subOwner2->uuid, sizeof(subOwner1->uuid)))
2078             {
2079                 OIC_LOG_V(ERROR, TAG, "%s: subOwner uuid mismatch", __func__);
2080                 return false;
2081             }
2082
2083             if (subOwner1->status != subOwner2->status)
2084             {
2085                 OIC_LOG_V(ERROR, TAG, "%s: subOwner status mismatch: (%u, %u)", 
2086                     __func__, (uint32_t)subOwner1->status, (uint32_t)subOwner2->status);
2087                 return false;
2088             }
2089
2090             //Go to the next elements from the two lists.
2091             subOwner1 = subOwner1->next;
2092             subOwner2 = subOwner2->next;
2093             continue;
2094         }
2095      
2096         OIC_LOG_V(ERROR, TAG, "%s: subOwner list length mismatch", __func__);
2097         return false;
2098     }
2099
2100     // Compare the mom values.
2101     if (NULL == doxm1->mom)
2102     {
2103         if (NULL != doxm2->mom)
2104         {
2105             OIC_LOG_V(ERROR, TAG, "%s: doxm1->mom is NULL", __func__);
2106             return false;
2107         }
2108
2109         return true;
2110     }
2111
2112     if (NULL == doxm2->mom)
2113     {
2114         OIC_LOG_V(ERROR, TAG, "%s: doxm2->mom is NULL", __func__);
2115         return false;
2116     }
2117
2118     if (doxm1->mom->mode != doxm2->mom->mode)
2119     {
2120         OIC_LOG_V(ERROR, TAG, "%s: mom->mode mismatch: (%u, %u)", 
2121             __func__, (uint32_t)doxm1->mom->mode, (uint32_t)doxm2->mom->mode);
2122         return false;
2123     }
2124
2125     return true;
2126 }
2127 #endif //#ifdef MULTIPLE_OWNER
2128
2129 bool AreDoxmBinPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2130 {
2131     if (NULL == doxm1 || NULL == doxm2)
2132     {
2133         OIC_LOG_V(ERROR, TAG, "%s: unxpected NULL doxm pointer", __func__);
2134         return false;
2135     }
2136
2137     //Compare the contents of the oxmType array and its length oxmTypeLen.
2138     size_t arrayLength = doxm1->oxmTypeLen;
2139
2140     if (arrayLength != doxm2->oxmTypeLen)
2141     {
2142         OIC_LOG_V(ERROR, TAG, "%s: oxmTypeLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")", 
2143             __func__, arrayLength, doxm2->oxmTypeLen);
2144         return false;
2145     }
2146
2147     for (size_t i = 0; i < arrayLength; i++)
2148     {
2149         if (NULL == doxm1->oxmType[i] || NULL == doxm2->oxmType[i])
2150         {
2151             OIC_LOG_V(ERROR, TAG, "%s: unexpected NULL found in the oxmType array",
2152                 __func__);
2153             return false;
2154         }
2155
2156         if (0 != strcmp(doxm1->oxmType[i], doxm2->oxmType[i]))
2157         {
2158             OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%s, %s)", 
2159                 __func__, doxm1->oxmType[i], doxm2->oxmType[i]);
2160             return false;
2161         }
2162     }
2163
2164     //Compare the contents of the oxm array and its length oxmLen.
2165     arrayLength = doxm1->oxmLen;
2166
2167     if (arrayLength != doxm2->oxmLen)
2168     {
2169         OIC_LOG_V(ERROR, TAG, "%s: oxmLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")", 
2170             __func__, arrayLength, doxm2->oxmLen);
2171         return false;
2172     }
2173    
2174     for (size_t i = 0; i < arrayLength; i++)
2175     {
2176         if (doxm1->oxm[i] != doxm2->oxm[i])
2177         {
2178             OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%u, %u)", 
2179                 __func__, (uint32_t)doxm1->oxm[i], (uint32_t)doxm2->oxm[i]);
2180             return false;
2181         }
2182     }
2183
2184     //Compare the remaining property values.
2185     if (doxm1->oxmSel != doxm2->oxmSel)
2186     {
2187         OIC_LOG_V(ERROR, TAG, "%s: oxmSel mismatch: (%u, %u)", 
2188             __func__, (uint32_t)doxm1->oxmSel, (uint32_t)doxm2->oxmSel);
2189         return false;
2190     }
2191
2192     if (doxm1->sct != doxm2->sct)
2193     {
2194         OIC_LOG_V(ERROR, TAG, "%s: sct mismatch: (%u, %u)", 
2195             __func__, (uint32_t)doxm1->sct, (uint32_t)doxm2->sct);
2196         return false;
2197     }
2198
2199     if (doxm1->owned != doxm2->owned)
2200     {
2201         OIC_LOG_V(ERROR, TAG, "%s: owned mismatch: (%u, %u)", 
2202             __func__, (uint32_t)doxm1->owned, (uint32_t)doxm2->owned);
2203         return false;
2204     }
2205
2206     if (0 != memcmp(&doxm1->deviceID, &doxm2->deviceID, sizeof(doxm1->deviceID)))
2207     {
2208         OIC_LOG_V(ERROR, TAG, "%s: deviceID mismatch", __func__);
2209         return false;
2210     }
2211     
2212     if (doxm1->dpc != doxm2->dpc)
2213     {
2214         OIC_LOG_V(ERROR, TAG, "%s: dpc mismatch: (%u, %u)", 
2215             __func__, (uint32_t)doxm1->dpc, (uint32_t)doxm2->dpc);
2216         return false;
2217     }
2218
2219     if (0 != memcmp(&doxm1->owner, &doxm2->owner, sizeof(doxm1->owner)))
2220     {
2221         OIC_LOG_V(ERROR, TAG, "%s: owner mismatch", __func__);
2222         return false;
2223     }
2224     
2225     if (0 != memcmp(&doxm1->rownerID, &doxm2->rownerID, sizeof(doxm1->rownerID)))
2226     {
2227         OIC_LOG_V(ERROR, TAG, "%s: rownerID mismatch", __func__);
2228         return false;
2229     }
2230
2231 #ifdef MULTIPLE_OWNER
2232     return AreDoxmBinMOTPropertyValuesEqual(doxm1, doxm2);
2233 #else
2234     return true;
2235 #endif
2236 }