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