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