[IOT-2821] Fix /doxm Update handling
[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         bool isDuplicatedMsg)
1338 {
1339     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1340     OCEntityHandlerResult ehRet = OC_EH_OK;
1341
1342 #if !(defined(__WITH_DTLS__) || defined(__WITH_TLS__))
1343     OC_UNUSED(isDuplicatedMsg);
1344     OC_UNUSED(ehRequest);
1345 #endif // not __WITH_DTLS__ and not __WITH_TLS__
1346
1347     // if /doxm.devowneruuid = Nil UUID, just enable Anon Cipher Suite
1348     if (IsNilUuid(&gDoxm->owner))
1349     {
1350 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1351         OCStackResult res = EnableAnonCipherSuiteIfUnOwnedAndJustWorksSelected(NULL);
1352         if (OC_STACK_OK != res)
1353         {
1354             ehRet = OC_EH_ERROR;
1355         }
1356 #endif // __WITH_DTLS__ or __WITH_TLS__
1357         goto exit;
1358     }
1359     // else if /doxm.devowneruuid != Nil UUID, disable Anon CipherSuite
1360     else
1361     {
1362 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1363         // Disable anonymous ECDH cipher since OTM is underway
1364         RegisterOTMSslHandshakeCallback(NULL);
1365         CAResult_t caRes = CA_STATUS_OK;
1366         caRes = CAEnableAnonECDHCipherSuite(false);
1367         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1368         OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1369
1370         //In case of Mutual Verified Just-Works, verify mutualVerifNum
1371         if (OIC_MV_JUST_WORKS == gDoxm->oxmSel && false == gDoxm->owned &&
1372             false == isDuplicatedMsg)
1373         {
1374             uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1375             uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1376             OicUuid_t deviceID = {.id = {0}};
1377
1378             //Generate mutualVerifNum
1379             OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1380
1381             char label[LABEL_LEN] = {0};
1382             snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1383             if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1384             {
1385                 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1386                 ehRet = OC_EH_ERROR;
1387                 goto exit;
1388
1389             }
1390
1391             CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1392              (uint8_t *)label,
1393              strlen(label),
1394              gDoxm->owner.id, sizeof(gDoxm->owner.id),
1395              gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1396              preMutualVerifNum, OWNER_PSK_LENGTH_128);
1397             if (CA_STATUS_OK != pskRet)
1398             {
1399                 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1400                 ehRet = OC_EH_ERROR;
1401                 goto exit;
1402
1403             }
1404
1405             memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1406              sizeof(mutualVerifNum));
1407
1408             //Wait for user confirmation
1409             if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1410             {
1411                 ehRet = OC_EH_NOT_ACCEPTABLE;
1412             }
1413             else
1414             {
1415                 ehRet = OC_EH_OK;
1416             }
1417         }
1418 #endif // __WITH_DTLS__ or __WITH_TLS__
1419     }
1420 exit:
1421     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1422     return ehRet;
1423 }
1424
1425 OCEntityHandlerResult HandleDoxmPostRequestRandomPin(OicSecDoxm_t *newDoxm,
1426         OCEntityHandlerRequest *ehRequest,
1427         bool isDuplicatedMsg)
1428 {
1429     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1430     OCEntityHandlerResult ehRet = OC_EH_OK;
1431
1432 #if !(defined(__WITH_DTLS__) || defined(__WITH_TLS__))
1433     OC_UNUSED(isDuplicatedMsg);
1434     OC_UNUSED(ehRequest);
1435 #endif // not __WITH_DTLS__ and not __WITH_TLS__
1436
1437     if (IsNilUuid(&newDoxm->owner))
1438     {
1439         gDoxm->oxmSel = newDoxm->oxmSel;
1440         /*
1441         * If current state of the device is un-owned, enable
1442         * ECDHE_PSK cipher so that the Provisioning tool can
1443         * initiate the ownership transfer.
1444         */
1445 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1446         CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1447         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1448         OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1449
1450         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1451         caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1452                                     (CATransportAdapter_t)ehRequest->devAddr.adapter);
1453         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1454
1455         if (!isDuplicatedMsg)
1456         {
1457             char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1458             if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1459             {
1460                 //Set the device id to derive temporal PSK
1461                 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1462
1463                 /**
1464                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1465                  * Credential should not be saved into SVR.
1466                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1467                  */
1468                 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1469                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1470                 ehRet = OC_EH_OK;
1471             }
1472             else
1473             {
1474                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1475                 ehRet = OC_EH_ERROR;
1476             }
1477         }
1478 #endif // __WITH_DTLS__ or __WITH_TLS__
1479     }
1480 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1481     else
1482     {
1483         //Save the owner's UUID to derive owner credential
1484         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1485
1486         // In case of random-pin based OTM, close the PIN display if callback is registered.
1487         if (!isDuplicatedMsg)
1488         {
1489             ClosePinDisplay();
1490         }
1491     }
1492 #endif // __WITH_DTLS__ or __WITH_TLS__
1493     goto exit;
1494 exit:
1495     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1496     return ehRet;
1497 }
1498
1499 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1500 OCEntityHandlerResult HandleDoxmPostRequestMfg(OicSecDoxm_t *newDoxm,
1501         OCEntityHandlerRequest *ehRequest,
1502         bool isDuplicatedMsg)
1503 {
1504     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1505     OCEntityHandlerResult ehRet = OC_EH_OK;
1506
1507
1508         //In case of Confirm Manufacturer Cert, get user confirmation
1509         if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1510             false == isDuplicatedMsg && !IsNilUuid(&newDoxm->owner))
1511         {
1512             if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1513             {
1514                 ehRet = OC_EH_NOT_ACCEPTABLE;
1515                 goto exit;
1516             }
1517             else
1518             {
1519                 ehRet = OC_EH_OK;
1520             }
1521         }
1522
1523         //Save the owner's UUID to derive owner credential
1524         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1525         gDoxm->oxmSel = newDoxm->oxmSel;
1526
1527         RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1528         CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1529         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1530         OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1531
1532         //Unset pre-selected ciphersuite, if any
1533         caRes = CASelectCipherSuite(0,(CATransportAdapter_t)ehRequest->devAddr.adapter);
1534         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1535         OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
1536
1537         VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1538         VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(
1539                            InitManufacturerCipherSuiteList), ERROR);
1540 exit:
1541     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1542     return ehRet;
1543     }
1544 #endif // __WITH_DTLS__ or __WITH_TLS__
1545
1546 // Do OTM specific initiation steps
1547 OCEntityHandlerResult StartOwnershipTransfer(OicSecDoxm_t *newDoxm,
1548         OCEntityHandlerRequest *ehRequest,
1549         bool isDuplicatedMsg)
1550 {
1551     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1552     OCEntityHandlerResult ehRet = OC_EH_OK;
1553
1554     switch (newDoxm->oxmSel)
1555     {
1556         case OIC_JUST_WORKS:
1557         case OIC_MV_JUST_WORKS:
1558             ehRet = StartOTMJustWorks(ehRequest, isDuplicatedMsg);
1559             break;
1560         case OIC_RANDOM_DEVICE_PIN:
1561             ehRet = HandleDoxmPostRequestRandomPin(newDoxm, ehRequest, isDuplicatedMsg);
1562             break;
1563 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1564         case OIC_MANUFACTURER_CERTIFICATE:
1565         case OIC_CON_MFG_CERT:
1566             ehRet = HandleDoxmPostRequestMfg(newDoxm, ehRequest, isDuplicatedMsg);
1567             break;
1568 #endif // __WITH_DTLS__ or __WITH_TLS__
1569         default:
1570             break;
1571     }
1572
1573     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1574     return ehRet;
1575 }
1576
1577
1578 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest *ehRequest)
1579 {
1580     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1581     OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
1582     static uint16_t previousMsgId = 0;
1583     bool isDuplicatedMsg = false;
1584     bool fACE = false;
1585     OicSecDoxm_t *newDoxm = NULL;
1586     bool roParsed = false;
1587     bool oxmselParsed = false;
1588     OicSecDostype_t dos;
1589
1590     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
1591     VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
1592     VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
1593
1594     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
1595
1596     // Check if /doxm is read-only.
1597     if (DOS_RESET == dos.state ||
1598         DOS_RFNOP == dos.state)
1599     {
1600         OIC_LOG_V(ERROR, TAG, "%s /doxm resource is read-only in RESET or RFNOP", __func__);
1601         ehRet = OC_EH_NOT_ACCEPTABLE;
1602         goto exit;
1603     }
1604
1605     // Convert CBOR Doxm data into binary. This will also validate
1606     // the Doxm data received.
1607     uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1608     VERIFY_NOT_NULL(TAG, payload, ERROR);
1609     size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1610     OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed,
1611                         &oxmselParsed, dos.state);
1612     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1613     VERIFY_NOT_NULL(TAG, newDoxm, ERROR);
1614     if (true == roParsed)
1615     {
1616         OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
1617         ehRet = OC_EH_NOT_ACCEPTABLE;
1618         goto exit;
1619     }
1620
1621     /*
1622      * message ID is supported for CoAP over UDP only according to RFC 7252
1623      * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1624      * In case of other transport adapter, duplicate message check is not required.
1625      */
1626     if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1627         previousMsgId == ehRequest->messageID)
1628     {
1629         isDuplicatedMsg = true;
1630     }
1631
1632     // Validate newDoxm->oxmsel first
1633     if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1634     {
1635         OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel is not supported on Server");
1636         ehRet = OC_EH_NOT_ACCEPTABLE;
1637         goto exit;
1638     }
1639
1640     // Valid oxmsel and no read-only Property parsed, so update gDoxm based on newDoxm
1641     res = DoxmUpdateWriteableProperty(newDoxm, gDoxm);
1642     if (OC_STACK_OK != res)
1643     {
1644         OIC_LOG(ERROR, TAG,
1645             "gDoxm properties were not able to be updated so we cannot handle the request.");
1646         ehRet = OC_EH_ERROR;
1647         goto exit;
1648     }
1649
1650     // If oxmsel was in Update payload, and the device is not owned,
1651     // do the OTM-specific aspect of owner-transfer
1652     if (oxmselParsed && (false == gDoxm->owned))
1653     {
1654         OIC_LOG_V(INFO, TAG, "%s: Device not owned and oxmsel Updated... starting OTM!", __func__);
1655         ehRet = StartOwnershipTransfer(newDoxm, ehRequest, isDuplicatedMsg);
1656         VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
1657     }
1658
1659 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1660 #ifdef MULTIPLE_OWNER
1661     HandleDoxmPostRequestMom(newDoxm, ehRequest);
1662 #endif //MULTIPLE_OWNER
1663 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1664
1665  #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1666     if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1667         OIC_CON_MFG_CERT == gDoxm->oxmSel)
1668     {
1669         CAregisterPkixInfoHandler(GetPkixInfo);
1670         CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1671     }
1672 #endif // __WITH_DTLS__ or __WITH_TLS__
1673
1674     // Update new state in persistent storage
1675     ehRet = HandleDoxmPostRequestUpdatePS(fACE);
1676
1677 exit:
1678     if (OC_EH_OK != ehRet)
1679     {
1680         // If some error is occured during Update handler,
1681         // revert /doxm and /pstat back to initial status.
1682
1683         if (gDoxm)
1684         {
1685             if (!isDuplicatedMsg)
1686             {
1687                 RestoreDoxmToInitState();
1688                 RestorePstatToInitState();
1689                 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1690             }
1691         }
1692         else
1693         {
1694             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1695         }
1696     }
1697     else
1698     {
1699         previousMsgId = ehRequest->messageID;
1700     }
1701
1702     //Send payload to request originator
1703     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1704             OC_EH_OK : OC_EH_ERROR;
1705
1706     DeleteDoxmBinData(newDoxm);
1707
1708     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1709
1710     return ehRet;
1711 }
1712
1713
1714 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1715                                         OCEntityHandlerRequest * ehRequest,
1716                                         void* callbackParam)
1717 {
1718     (void)callbackParam;
1719     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1720
1721     if(NULL == ehRequest)
1722     {
1723         return ehRet;
1724     }
1725
1726     if (flag & OC_REQUEST_FLAG)
1727     {
1728         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1729
1730         switch (ehRequest->method)
1731         {
1732             case OC_REST_GET:
1733                 ehRet = HandleDoxmGetRequest(ehRequest);
1734                 break;
1735
1736             case OC_REST_POST:
1737                 ehRet = HandleDoxmPostRequest(ehRequest);
1738                 break;
1739
1740             default:
1741                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1742                                OC_EH_OK : OC_EH_ERROR;
1743                 break;
1744         }
1745     }
1746
1747     return ehRet;
1748 }
1749
1750 OCStackResult CreateDoxmResource()
1751 {
1752     OCStackResult ret = OCCreateResource(&gDoxmHandle,
1753                                          OIC_RSRC_TYPE_SEC_DOXM,
1754                                          OC_RSRVD_INTERFACE_DEFAULT,
1755                                          OIC_RSRC_DOXM_URI,
1756                                          DoxmEntityHandler,
1757                                          NULL,
1758                                          OC_SECURE | OC_NONSECURE |
1759                                          OC_DISCOVERABLE);
1760
1761     if (OC_STACK_OK != ret)
1762     {
1763         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1764         DeInitDoxmResource();
1765     }
1766     return ret;
1767 }
1768
1769 /**
1770  * Checks if DeviceID is generated during provisioning for the new device.
1771  * If DeviceID is NULL then generates the new DeviceID.
1772  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1773  */
1774 static OCStackResult CheckDeviceID()
1775 {
1776     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1777
1778     OCStackResult ret = OC_STACK_ERROR;
1779     bool validId = false;
1780
1781     VERIFY_NOT_NULL_RETURN(TAG, gDoxm, ERROR, OC_STACK_INVALID_PARAM);
1782
1783     for (uint8_t i = 0; i < UUID_LENGTH; i++)
1784     {
1785         if (gDoxm->deviceID.id[i] != 0)
1786         {
1787             validId = true;
1788             break;
1789         }
1790     }
1791
1792     if (!validId)
1793     {
1794         char* strUuid = NULL;
1795 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1796         //If seed value is exists, generate UUID using seed with SHA256
1797         if (0 != gUuidSeedSize)
1798         {
1799             uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1800             int mbedret = 0;
1801
1802             OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1803             OIC_LOG(DEBUG, TAG, "Seed value : ");
1804             OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1805
1806             mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1807                                  gUuidSeed, gUuidSeedSize, hashVal);
1808             if(0 == mbedret)
1809             {
1810                 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1811                 ret = OC_STACK_OK;
1812             }
1813             else
1814             {
1815                 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1816                 ret = OC_STACK_ERROR;
1817             }
1818         }
1819         else
1820         {
1821             if (!OCGenerateUuid(gDoxm->deviceID.id))
1822             {
1823                 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1824                 ret = OC_STACK_ERROR;
1825             }
1826             else
1827             {
1828                 ret = OC_STACK_OK;
1829             }
1830         }
1831 #else
1832         if (!OCGenerateUuid(gDoxm->deviceID.id))
1833         {
1834             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1835             ret = OC_STACK_ERROR;
1836         }
1837         else
1838         {
1839             ret = OC_STACK_OK;
1840         }
1841 #endif
1842
1843         if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1844         {
1845             OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1846             OICFree(strUuid);
1847         }
1848         else
1849         {
1850             OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1851         }
1852
1853
1854         if (!UpdatePersistentStorage(gDoxm))
1855         {
1856             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1857             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1858         }
1859     }
1860     else
1861     {
1862         ret = OC_STACK_OK;
1863     }
1864
1865     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
1866
1867     return ret;
1868 }
1869
1870 /**
1871  * Get the default value.
1872  *
1873  * @return the default value of doxm, @ref OicSecDoxm_t.
1874  */
1875 static OicSecDoxm_t* GetDoxmDefault()
1876 {
1877     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1878     return &gDefaultDoxm;
1879 }
1880
1881 const OicSecDoxm_t* GetDoxmResourceData()
1882 {
1883     return gDoxm;
1884 }
1885
1886 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1887 /**
1888  * Internal API to prepare MOT
1889  */
1890 static void PrepareMOT(const OicSecDoxm_t* doxm)
1891 {
1892     OIC_LOG(INFO, TAG, "IN PrepareMOT");
1893     VERIFY_NOT_NULL(TAG, doxm, ERROR);
1894
1895     if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1896     {
1897         CAResult_t caRes = CA_STATUS_FAILED;
1898
1899         OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1900
1901         if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1902         {
1903             caRes = CAEnableAnonECDHCipherSuite(false);
1904             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1905             OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1906
1907             RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1908             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
1909             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1910 #ifdef __WITH_TLS__
1911             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
1912             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1913 #endif
1914             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1915
1916             //Set the device id to derive temporal PSK
1917             SetUuidForPinBasedOxm(&doxm->deviceID);
1918         }
1919         else
1920         {
1921             OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1922             return;
1923         }
1924
1925         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1926     }
1927
1928     OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1929     return;
1930 exit:
1931     OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1932 }
1933 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1934
1935 OCStackResult InitDoxmResource()
1936 {
1937     OCStackResult ret = OC_STACK_ERROR;
1938
1939     //Read DOXM resource from PS
1940     uint8_t *data = NULL;
1941     size_t size = 0;
1942     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1943     // If database read failed
1944     if (OC_STACK_OK != ret)
1945     {
1946        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1947     }
1948     if (data)
1949     {
1950        // Read DOXM resource from PS
1951        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1952     }
1953     /*
1954      * If SVR database in persistent storage got corrupted or
1955      * is not available for some reason, a default doxm is created
1956      * which allows user to initiate doxm provisioning again.
1957      */
1958      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1959     {
1960         gDoxm = GetDoxmDefault();
1961     }
1962
1963     //In case of the server is shut down unintentionally, we should initialize the owner
1964     if(gDoxm && (false == gDoxm->owned))
1965     {
1966         OicUuid_t emptyUuid = {.id={0}};
1967         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1968     }
1969
1970     ret = CheckDeviceID();
1971     if (ret == OC_STACK_OK)
1972     {
1973         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1974         //Instantiate 'oic.sec.doxm'
1975         ret = CreateDoxmResource();
1976     }
1977     else
1978     {
1979         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1980     }
1981     OICFree(data);
1982
1983 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1984     //if MOT is enabled, MOT should be prepared.
1985     if(gDoxm && gDoxm->owned)
1986     {
1987         PrepareMOT(gDoxm);
1988     }
1989 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1990
1991 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1992     bool isAnonEnabled = false;
1993     if (OC_STACK_OK != EnableAnonCipherSuiteIfUnOwnedAndJustWorksSelected(&isAnonEnabled))
1994     {
1995         ret = OC_STACK_ERROR;
1996     }
1997     OIC_LOG_V(INFO, TAG, "%s: Anon Ciphersuite %sENABLED.", __func__,
1998         isAnonEnabled ? "" : "NOT ");
1999 #endif // __WITH_DTLS__ or __WITH_TLS__
2000
2001     return ret;
2002 }
2003
2004 OCStackResult DeInitDoxmResource()
2005 {
2006     OCStackResult ret = OCDeleteResource(gDoxmHandle);
2007     if (gDoxm  != &gDefaultDoxm)
2008     {
2009         DeleteDoxmBinData(gDoxm);
2010     }
2011     gDoxm = NULL;
2012
2013     if (OC_STACK_OK == ret)
2014     {
2015         return OC_STACK_OK;
2016     }
2017     else
2018     {
2019         return OC_STACK_ERROR;
2020     }
2021 }
2022
2023 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
2024 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
2025 {
2026     OIC_LOG_V(INFO, TAG, "In %s", __func__);
2027
2028     if (NULL == seed)
2029     {
2030         return OC_STACK_INVALID_PARAM;
2031     }
2032     if (MAX_UUID_SEED_SIZE < seedSize)
2033     {
2034         OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
2035         return OC_STACK_INVALID_PARAM;
2036     }
2037     if (MIN_UUID_SEED_SIZE > seedSize)
2038     {
2039         OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
2040         return OC_STACK_INVALID_PARAM;
2041     }
2042
2043     memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
2044     memcpy(gUuidSeed, seed, seedSize);
2045     gUuidSeedSize = seedSize;
2046
2047     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
2048
2049     return OC_STACK_OK;
2050 }
2051 #endif
2052
2053 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceuuid)
2054 {
2055     if (deviceuuid && gDoxm)
2056     {
2057         *deviceuuid = gDoxm->deviceID;
2058         return OC_STACK_OK;
2059     }
2060     return OC_STACK_ERROR;
2061 }
2062
2063 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceuuid)
2064 {
2065     bool isOwnerUpdated = false;
2066     bool isRownerUpdated = false;
2067     if (NULL == deviceuuid)
2068     {
2069         return OC_STACK_INVALID_PARAM;
2070     }
2071     if (NULL == gDoxm)
2072     {
2073         OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
2074         return OC_STACK_NO_RESOURCE;
2075     }
2076
2077 #ifdef __WITH_DTLS__
2078     //for normal device.
2079     if (true == gDoxm->owned &&
2080         memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
2081     {
2082         OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
2083         OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
2084         return OC_STACK_ERROR;
2085     }
2086 #endif //__WITH_DTLS
2087
2088     //Save the previous UUID
2089     OicUuid_t prevUuid;
2090     memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
2091
2092     //Change the device UUID
2093     memcpy(gDoxm->deviceID.id, deviceuuid->id, sizeof(gDoxm->deviceID.id));
2094
2095     //Change the owner ID if necessary
2096     if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2097     {
2098         memcpy(gDoxm->owner.id, deviceuuid->id, sizeof(gDoxm->owner.id));
2099         isOwnerUpdated = true;
2100     }
2101     //Change the resource owner ID if necessary
2102     // TODO [IOT-2023] change this behavior and upate the usage of this function
2103     // so that rowneruuid for each resource is set by OBT
2104     if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2105     {
2106         memcpy(gDoxm->rownerID.id, deviceuuid->id, sizeof(gDoxm->rownerID.id));
2107         isRownerUpdated = true;
2108     }
2109
2110     //Update PS
2111     if (!UpdatePersistentStorage(gDoxm))
2112     {
2113         //revert UUID in case of PSI error
2114         memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(gDoxm->deviceID.id));
2115         if (isOwnerUpdated)
2116         {
2117             memcpy(gDoxm->owner.id, prevUuid.id, sizeof(gDoxm->owner.id));
2118         }
2119         if (isRownerUpdated)
2120         {
2121             memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(gDoxm->rownerID.id));
2122         }
2123
2124         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
2125         return OC_STACK_ERROR;
2126     }
2127     return OC_STACK_OK;
2128 }
2129
2130 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devowneruuid)
2131 {
2132     if (gDoxm && devowneruuid)
2133     {
2134         memcpy(&(devowneruuid->id), &(gDoxm->owner.id), sizeof(devowneruuid->id));
2135         return OC_STACK_OK;
2136     }
2137     return OC_STACK_ERROR;
2138 }
2139
2140 OCStackResult SetDoxmDevOwnerId(const OicUuid_t *devowneruuid)
2141 {
2142     if (gDoxm && devowneruuid)
2143     {
2144         memcpy(&(gDoxm->owner.id), &(devowneruuid->id), sizeof(gDoxm->owner.id));
2145         return OC_STACK_OK;
2146     }
2147     return OC_STACK_ERROR;
2148 }
2149
2150 OCStackResult GetDoxmIsOwned(bool *isowned)
2151 {
2152     if (isowned && gDoxm)
2153     {
2154         *isowned = gDoxm->owned;
2155         return OC_STACK_OK;
2156     }
2157     return OC_STACK_ERROR;
2158 }
2159
2160 OCStackResult SetDoxmIsOwned(const bool isowned)
2161 {
2162     if (gDoxm)
2163     {
2164         gDoxm->owned = isowned;
2165         return OC_STACK_OK;
2166     }
2167     return OC_STACK_ERROR;
2168 }
2169
2170 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
2171 {
2172     if (gDoxm && rowneruuid)
2173     {
2174         memcpy(&(rowneruuid->id), &(gDoxm->rownerID.id), sizeof(rowneruuid->id));
2175         return OC_STACK_OK;
2176     }
2177     return OC_STACK_ERROR;
2178 }
2179
2180 OCStackResult SetDoxmRownerId(const OicUuid_t *rowneruuid)
2181 {
2182     if (gDoxm && rowneruuid)
2183     {
2184         memcpy(&(gDoxm->rownerID.id), &(rowneruuid->id), sizeof(gDoxm->rownerID.id));
2185         return OC_STACK_OK;
2186     }
2187     return OC_STACK_ERROR;
2188 }
2189
2190 #ifdef MULTIPLE_OWNER
2191 /**
2192  * Compare the UUID to SubOwner.
2193  *
2194  * @param[in] uuid device UUID
2195  *
2196  * @return true if context->subjectId exist subowner list, else false.
2197  */
2198 bool IsSubOwner(const OicUuid_t* uuid)
2199 {
2200     bool retVal = false;
2201
2202     if (NULL == uuid)
2203     {
2204         return retVal;
2205     }
2206
2207     if (gDoxm && gDoxm->subOwners)
2208     {
2209         if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
2210         {
2211             return false;
2212         }
2213
2214         OicSecSubOwner_t* subOwner = NULL;
2215         LL_FOREACH(gDoxm->subOwners, subOwner)
2216         {
2217             if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
2218             {
2219                 return true;
2220             }
2221         }
2222     }
2223     return retVal;
2224 }
2225
2226 OCStackResult SetMOTStatus(bool enable)
2227 {
2228     OCStackResult ret = OC_STACK_NO_MEMORY;
2229     uint8_t *cborPayload = NULL;
2230     size_t size = 0;
2231     bool isDeallocateRequired = false;
2232
2233     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2234
2235     VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
2236
2237     if (NULL == gDoxm->mom && !enable)
2238     {
2239         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2240         return OC_STACK_OK;
2241     }
2242
2243     if (NULL == gDoxm->mom)
2244     {
2245         gDoxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
2246         VERIFY_NOT_NULL(TAG, gDoxm->mom, ERROR);
2247         isDeallocateRequired = true;
2248     }
2249
2250     gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
2251
2252     ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size);
2253     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2254
2255     ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2256     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2257
2258     isDeallocateRequired = false;
2259
2260 exit:
2261     if (isDeallocateRequired)
2262     {
2263         OICFree(gDoxm->mom);
2264     }
2265     OICFree(cborPayload);
2266     OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
2267     return ret;
2268 }
2269
2270 #endif //MULTIPLE_OWNER
2271
2272 /**
2273  * Function to restore doxm resurce to initial status.
2274  * This function will use in case of error while ownership transfer
2275  */
2276 void RestoreDoxmToInitState()
2277 {
2278     if(gDoxm)
2279     {
2280         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
2281
2282         OicUuid_t emptyUuid = {.id={0}};
2283         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
2284         gDoxm->owned = false;
2285         gDoxm->oxmSel = OIC_JUST_WORKS;
2286
2287         if(!UpdatePersistentStorage(gDoxm))
2288         {
2289             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2290         }
2291     }
2292 }
2293
2294 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2295 {
2296     OCStackResult ret = OC_STACK_ERROR;
2297     uint8_t *cborPayload = NULL;
2298     size_t size = 0;
2299
2300     if(NULL == gDoxm)
2301     {
2302         ret = OC_STACK_NO_RESOURCE;
2303         return ret;
2304     }
2305
2306     if( newROwner && (false == gDoxm->owned) )
2307     {
2308         gDoxm->owned = true;
2309         memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2310         memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2311
2312         ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size);
2313         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2314
2315         ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2316         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2317
2318         OICFree(cborPayload);
2319     }
2320
2321     return ret;
2322
2323 exit:
2324     OICFree(cborPayload);
2325     return ret;
2326 }
2327
2328 #ifdef MULTIPLE_OWNER
2329 /** This function checks if two sets of /oic/sec/doxm MOT-specific properties are identical.
2330  *
2331  * @param doxm1 is a pointer to the first @ref OicSecDoxm_t data.
2332  * @param doxm2 is a pointer to the second @ref OicSecDoxm_t data.
2333  *
2334  * @return true if all of the properties are identical, else false.
2335  */
2336 static bool AreDoxmBinMOTPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2337 {
2338     //Compare the subOwners lists.
2339     OicSecSubOwner_t* subOwner1 = doxm1->subOwners;
2340     OicSecSubOwner_t* subOwner2 = doxm2->subOwners;
2341
2342     for (;;)
2343     {
2344         if ((NULL == subOwner1) && (NULL == subOwner2))
2345         {
2346             //Reached the end of both lists, so the two lists were identical.
2347             break;
2348         }
2349
2350         if ((NULL != subOwner1) && (NULL != subOwner2))
2351         {
2352             if (0 != memcmp(&subOwner1->uuid, &subOwner2->uuid, sizeof(subOwner1->uuid)))
2353             {
2354                 OIC_LOG_V(ERROR, TAG, "%s: subOwner uuid mismatch", __func__);
2355                 return false;
2356             }
2357
2358             if (subOwner1->status != subOwner2->status)
2359             {
2360                 OIC_LOG_V(ERROR, TAG, "%s: subOwner status mismatch: (%u, %u)",
2361                     __func__, (uint32_t)subOwner1->status, (uint32_t)subOwner2->status);
2362                 return false;
2363             }
2364
2365             //Go to the next elements from the two lists.
2366             subOwner1 = subOwner1->next;
2367             subOwner2 = subOwner2->next;
2368             continue;
2369         }
2370
2371         OIC_LOG_V(ERROR, TAG, "%s: subOwner list length mismatch", __func__);
2372         return false;
2373     }
2374
2375     // Compare the mom values.
2376     if (NULL == doxm1->mom)
2377     {
2378         if (NULL != doxm2->mom)
2379         {
2380             OIC_LOG_V(ERROR, TAG, "%s: doxm1->mom is NULL", __func__);
2381             return false;
2382         }
2383
2384         return true;
2385     }
2386
2387     if (NULL == doxm2->mom)
2388     {
2389         OIC_LOG_V(ERROR, TAG, "%s: doxm2->mom is NULL", __func__);
2390         return false;
2391     }
2392
2393     if (doxm1->mom->mode != doxm2->mom->mode)
2394     {
2395         OIC_LOG_V(ERROR, TAG, "%s: mom->mode mismatch: (%u, %u)",
2396             __func__, (uint32_t)doxm1->mom->mode, (uint32_t)doxm2->mom->mode);
2397         return false;
2398     }
2399
2400     return true;
2401 }
2402 #endif //#ifdef MULTIPLE_OWNER
2403
2404 bool AreDoxmBinPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2405 {
2406     if (NULL == doxm1 || NULL == doxm2)
2407     {
2408         OIC_LOG_V(ERROR, TAG, "%s: unxpected NULL doxm pointer", __func__);
2409         return false;
2410     }
2411
2412     //Compare the contents of the oxm array and its length oxmLen.
2413     size_t arrayLength = doxm1->oxmLen;
2414
2415     if (arrayLength != doxm2->oxmLen)
2416     {
2417         OIC_LOG_V(ERROR, TAG, "%s: oxmLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
2418             __func__, arrayLength, doxm2->oxmLen);
2419         return false;
2420     }
2421
2422     for (size_t i = 0; i < arrayLength; i++)
2423     {
2424         if (doxm1->oxm[i] != doxm2->oxm[i])
2425         {
2426             OIC_LOG_V(ERROR, TAG, "%s: oxm mismatch: (%u, %u)",
2427                 __func__, (uint32_t)doxm1->oxm[i], (uint32_t)doxm2->oxm[i]);
2428             return false;
2429         }
2430     }
2431
2432     //Compare the remaining property values.
2433     if (doxm1->oxmSel != doxm2->oxmSel)
2434     {
2435         OIC_LOG_V(ERROR, TAG, "%s: oxmSel mismatch: (%u, %u)",
2436             __func__, (uint32_t)doxm1->oxmSel, (uint32_t)doxm2->oxmSel);
2437         return false;
2438     }
2439
2440     if (doxm1->sct != doxm2->sct)
2441     {
2442         OIC_LOG_V(ERROR, TAG, "%s: sct mismatch: (%u, %u)",
2443             __func__, (uint32_t)doxm1->sct, (uint32_t)doxm2->sct);
2444         return false;
2445     }
2446
2447     if (doxm1->owned != doxm2->owned)
2448     {
2449         OIC_LOG_V(ERROR, TAG, "%s: owned mismatch: (%u, %u)",
2450             __func__, (uint32_t)doxm1->owned, (uint32_t)doxm2->owned);
2451         return false;
2452     }
2453
2454     if (0 != memcmp(&doxm1->deviceID, &doxm2->deviceID, sizeof(doxm1->deviceID)))
2455     {
2456         OIC_LOG_V(ERROR, TAG, "%s: deviceID mismatch", __func__);
2457         return false;
2458     }
2459
2460     if (doxm1->dpc != doxm2->dpc)
2461     {
2462         OIC_LOG_V(ERROR, TAG, "%s: dpc mismatch: (%u, %u)",
2463             __func__, (uint32_t)doxm1->dpc, (uint32_t)doxm2->dpc);
2464         return false;
2465     }
2466
2467     if (0 != memcmp(&doxm1->owner, &doxm2->owner, sizeof(doxm1->owner)))
2468     {
2469         OIC_LOG_V(ERROR, TAG, "%s: owner mismatch", __func__);
2470         return false;
2471     }
2472
2473     if (0 != memcmp(&doxm1->rownerID, &doxm2->rownerID, sizeof(doxm1->rownerID)))
2474     {
2475         OIC_LOG_V(ERROR, TAG, "%s: rownerID mismatch", __func__);
2476         return false;
2477     }
2478
2479 #ifdef MULTIPLE_OWNER
2480     return AreDoxmBinMOTPropertyValuesEqual(doxm1, doxm2);
2481 #else
2482     return true;
2483 #endif
2484 }
2485
2486 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2487 OCStackResult EnableAnonCipherSuiteIfUnOwnedAndJustWorksSelected(bool *enabled)
2488 {
2489     OCStackResult ret = OC_STACK_ERROR;
2490
2491     OIC_LOG_V(INFO, TAG, "%s: function enter.", __func__);
2492
2493     // If device unowned, check if JW OTM is selected.
2494     // If so, register handshake callback, and enable Anon Ciphersuite.
2495     if (NULL != gDoxm) {
2496         if (false == gDoxm->owned) {
2497             if (OIC_JUST_WORKS == gDoxm->oxmSel) {
2498                 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
2499                 OIC_LOG_V(INFO, TAG, "%s: enabling AnonECDHCipherSuite", __func__);
2500                 ret = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
2501                 if (OC_STACK_OK == ret)
2502                 {
2503                     OIC_LOG_V(INFO, TAG, "%s: AnonECDHCipherSuite ENABLED.", __func__);
2504                     if (NULL != enabled)
2505                     {
2506                         *enabled = true;
2507                     }
2508                 }
2509                 else
2510                 {
2511                     OIC_LOG_V(ERROR, TAG, "%s: Error attempting to enable AnonECDHCipherSuite!", __func__);
2512                 }
2513             }
2514             else
2515             {
2516                 OIC_LOG_V(INFO, TAG, "%s: JustWorks not selected; NOT enabling AnonECDHCipherSuite.", __func__);
2517                 ret = OC_STACK_OK;
2518             }
2519         }
2520         else
2521         {
2522             OIC_LOG_V(INFO, TAG, "%s: Device is owned; NOT enabling AnonECDHCipherSuite.", __func__);
2523             ret = OC_STACK_OK;
2524         }
2525     }
2526     else
2527     {
2528         OIC_LOG_V(INFO, TAG, "%s: gDoxm is NULL; NOT enabling AnonECDHCipherSuite.", __func__);
2529         ret = OC_STACK_OK;
2530     }
2531
2532     if (NULL != enabled)
2533     {
2534         if (true != *enabled)
2535         {
2536             *enabled = false;
2537         }
2538     }
2539
2540     OIC_LOG_V(INFO, TAG, "%s: function exit, returning %s.", __func__,
2541         (OC_STACK_OK == ret) ? "OC_STACK_OK" : "OC_STACK_ERROR");
2542
2543     return ret;
2544 }
2545 #endif // __WITH_DTLS__ or __WITH_TLS__