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