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