Update snapshot(2017-10-11)
[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 #endif
1242
1243                 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1244                 {
1245                     /*
1246                      * If current state of the device is un-owned, enable
1247                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
1248                      * tool can initiate JUST_WORKS ownership transfer process.
1249                      */
1250                     if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1251                     {
1252                         gDoxm->oxmSel = newDoxm->oxmSel;
1253                         //Update new state in persistent storage
1254                         if ((UpdatePersistentStorage(gDoxm) == true))
1255                         {
1256                             ehRet = OC_EH_OK;
1257                         }
1258                         else
1259                         {
1260                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1261                             ehRet = OC_EH_ERROR;
1262                             goto exit;
1263                         }
1264                         OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
1265 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1266                         ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1267 #endif // __WITH_DTLS__ or __WITH_TLS__
1268                         goto exit;
1269                     }
1270                     else
1271                     {
1272 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1273                         //Save the owner's UUID to derive owner credential
1274                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1275
1276                         // Update new state in persistent storage
1277                         if (true == UpdatePersistentStorage(gDoxm))
1278                         {
1279                             ehRet = OC_EH_OK;
1280                         }
1281                         else
1282                         {
1283                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1284                             ehRet = OC_EH_ERROR;
1285                             goto exit;
1286                         }
1287
1288                         /*
1289                          * Disable anonymous ECDH cipher in tinyDTLS since device is now
1290                          * in owned state.
1291                          */
1292                         CAResult_t caRes = CA_STATUS_OK;
1293                         caRes = CAEnableAnonECDHCipherSuite(false);
1294                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1295                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1296
1297                         //In case of Mutual Verified Just-Works, verify mutualVerifNum
1298                         if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1299                             false == isDuplicatedMsg)
1300                         {
1301                             uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1302                             uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1303                             OicUuid_t deviceID = {.id = {0}};
1304
1305                             //Generate mutualVerifNum
1306                             OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1307
1308                             char label[LABEL_LEN] = {0};
1309                             snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1310                             if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1311                             {
1312                                 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1313                                 ehRet = OC_EH_ERROR;
1314                                 goto exit;
1315
1316                             }
1317
1318                             CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1319                                     (uint8_t *)label,
1320                                     strlen(label),
1321                                     gDoxm->owner.id, sizeof(gDoxm->owner.id),
1322                                     gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1323                                     preMutualVerifNum, OWNER_PSK_LENGTH_128);
1324                             if (CA_STATUS_OK != pskRet)
1325                             {
1326                                 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1327                                 ehRet = OC_EH_ERROR;
1328                                 goto exit;
1329
1330                             }
1331
1332                             memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1333                                     sizeof(mutualVerifNum));
1334
1335                             gConfirmMsgId = ehRequest->messageID;
1336                             gConfirmState = CONFIRM_STATE_WAIT;
1337                             //Wait for user confirmation
1338                             if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1339                             {
1340                                 ehRet = OC_EH_NOT_ACCEPTABLE;
1341                                 gConfirmState = CONFIRM_STATE_DENIED;
1342                             }
1343                             else
1344                             {
1345                                 ehRet = OC_EH_OK;
1346                                 gConfirmState = CONFIRM_STATE_ACCEPTED;
1347                             }
1348                         }
1349
1350 #endif // __WITH_DTLS__ or __WITH_TLS__
1351                     }
1352                 }
1353                 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1354                 {
1355                     /*
1356                      * If current state of the device is un-owned, enable
1357                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
1358                      * tool can initiate JUST_WORKS ownership transfer process.
1359                      */
1360                     if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1361                     {
1362                         gDoxm->oxmSel = newDoxm->oxmSel;
1363                         //Update new state in persistent storage
1364                         if ((UpdatePersistentStorage(gDoxm) == true))
1365                         {
1366                             ehRet = OC_EH_OK;
1367                         }
1368                         else
1369                         {
1370                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1371                             ehRet = OC_EH_ERROR;
1372                         }
1373
1374 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1375                         CAResult_t caRes = CA_STATUS_OK;
1376
1377                         caRes = CAEnableAnonECDHCipherSuite(false);
1378                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1379                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1380
1381                         caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1382                                                     ehRequest->devAddr.adapter);
1383                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1384
1385                         if (!isDuplicatedMsg)
1386                         {
1387                             char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1388                             if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1389                             {
1390                                 //Set the device id to derive temporal PSK
1391                                 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1392
1393                                 /**
1394                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1395                                  * Credential should not be saved into SVR.
1396                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1397                                  */
1398                                 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1399                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1400                                 ehRet = OC_EH_OK;
1401                             }
1402                             else
1403                             {
1404                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1405                                 ehRet = OC_EH_ERROR;
1406                             }
1407                         }
1408 #endif // __WITH_DTLS__ or __WITH_TLS__
1409                     }
1410 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1411                     else
1412                     {
1413                         //Save the owner's UUID to derive owner credential
1414                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1415
1416                         // In case of random-pin based OTM, close the PIN display if callback is registered.
1417                         if (!isDuplicatedMsg)
1418                         {
1419                             ClosePinDisplay();
1420                         }
1421
1422                         //Update new state in persistent storage
1423                         if (UpdatePersistentStorage(gDoxm) == true)
1424                         {
1425                             ehRet = OC_EH_OK;
1426                         }
1427                         else
1428                         {
1429                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1430                             ehRet = OC_EH_ERROR;
1431                         }
1432                     }
1433 #endif // __WITH_DTLS__ or __WITH_TLS__
1434                 }
1435 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1436                 else if (OIC_MANUFACTURER_CERTIFICATE ==  newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1437                 {
1438                     //Get user confirmation
1439                     if (false == newDoxm->owned &&
1440                         false == isDuplicatedMsg &&
1441                         memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1442                     {
1443                         gConfirmMsgId = ehRequest->messageID;
1444                         gConfirmState = CONFIRM_STATE_WAIT;
1445                         if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1446                         {
1447                             ehRet = OC_EH_NOT_ACCEPTABLE;
1448                             gConfirmState = CONFIRM_STATE_DENIED;
1449                             goto exit;
1450                         }
1451                         else
1452                         {
1453                             ehRet = OC_EH_OK;
1454                             gConfirmState = CONFIRM_STATE_ACCEPTED;
1455                         }
1456                     }
1457
1458                     //Save the owner's UUID to derive owner credential
1459                     memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1460                     gDoxm->oxmSel = newDoxm->oxmSel;
1461                     //Update new state in persistent storage
1462                     if (UpdatePersistentStorage(gDoxm))
1463                     {
1464                         ehRet = OC_EH_OK;
1465                     }
1466                     else
1467                     {
1468                         OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1469                         ehRet = OC_EH_ERROR;
1470                     }
1471                     CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1472                     VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1473                     OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1474
1475                     //Unset pre-selected ciphersuite, if any
1476                     caRes = CASelectCipherSuite(0, ehRequest->devAddr.adapter);
1477                     VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1478                     OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
1479
1480                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1481                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1482                 }
1483 #endif // __WITH_DTLS__ or __WITH_TLS__
1484             }
1485
1486             /*
1487              * When current state of the device is un-owned and Provisioning
1488              * Tool is attempting to change the state to 'Owned' with a
1489              * qualified value for the field 'Owner'
1490              */
1491             if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1492                     (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1493             {
1494                 //Change the SVR's resource owner as owner device.
1495                 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1496                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1497                 {
1498                     ehRet = OC_EH_ERROR;
1499                     goto exit;
1500                 }
1501                 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1502                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1503                 {
1504                     ehRet = OC_EH_ERROR;
1505                     goto exit;
1506                 }
1507                 ownerRes = SetCredRownerId(&gDoxm->owner);
1508                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1509                 {
1510                     ehRet = OC_EH_ERROR;
1511                     goto exit;
1512                 }
1513                 ownerRes = SetPstatRownerId(&gDoxm->owner);
1514                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1515                 {
1516                     ehRet = OC_EH_ERROR;
1517                     goto exit;
1518                 }
1519
1520                 gDoxm->owned = true;
1521                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1522
1523                 // Update new state in persistent storage
1524                 if (UpdatePersistentStorage(gDoxm))
1525                 {
1526                     //Update default ACE of security resource to prevent anonymous user access.
1527                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
1528                     {
1529                         ehRet = OC_EH_OK;
1530                     }
1531                     else
1532                     {
1533                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1534                         ehRet = OC_EH_ERROR;
1535                     }
1536                 }
1537                 else
1538                 {
1539                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1540                     ehRet = OC_EH_ERROR;
1541                 }
1542 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1543                 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1544                                             OIC_CON_MFG_CERT== gDoxm->oxmSel)
1545                 {
1546                     CAregisterPkixInfoHandler(GetPkixInfo);
1547                     CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1548                 }
1549
1550                 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1551                                       &gDoxm->owner, OIC_OTM_DONE);
1552 #endif // __WITH_DTLS__ or __WITH_TLS__
1553             }
1554         }
1555     }
1556
1557 exit:
1558     if(OC_EH_OK != ehRet)
1559     {
1560         /*
1561          * If some error is occured while ownership transfer,
1562          * ownership transfer related resource should be revert back to initial status.
1563         */
1564         if(gDoxm)
1565         {
1566             if(!gDoxm->owned)
1567             {
1568                 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1569
1570                 if (!isDuplicatedMsg)
1571                 {
1572 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1573                     InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1574                                           NULL, OIC_OTM_ERROR);
1575 #endif
1576                     RestoreDoxmToInitState();
1577                     RestorePstatToInitState();
1578                     OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1579                 }
1580             }
1581         }
1582         else
1583         {
1584             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1585         }
1586     }
1587
1588     previousMsgId = ehRequest->messageID;
1589
1590 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1591     CAEndpoint_t peer = {0};
1592     OCDevAddr devAddr =  ehRequest->devAddr;
1593
1594     memcpy(&peer.addr, &devAddr.addr, sizeof(peer.addr));
1595     peer.port = devAddr.port;
1596     peer.adapter = (CATransportAdapter_t)devAddr.adapter;
1597
1598     if ((devAddr.flags & OC_FLAG_SECURE) && (false == CAIsExistSslPeer(&peer)))
1599     {
1600         OIC_LOG_V(WARNING, TAG, "Not Exist Peer");
1601         ehRet = OC_EH_OK;
1602     }
1603     else
1604     {
1605         //Send payload to request originator
1606         ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1607             OC_EH_OK : OC_EH_ERROR;
1608     }
1609 #else
1610     //Send payload to request originator
1611     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1612         OC_EH_OK : OC_EH_ERROR;
1613 #endif
1614
1615     DeleteDoxmBinData(newDoxm);
1616
1617     return ehRet;
1618 }
1619
1620 #ifdef MULTIPLE_OWNER
1621 static OCEntityHandlerResult HandleDoxmDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1622 {
1623     OIC_LOG(DEBUG, TAG, "Processing DoxmDeleteRequest");
1624
1625     OCEntityHandlerResult ehRet = OC_EH_BAD_REQ;
1626
1627     if (NULL == ehRequest->query)
1628     {
1629         return ehRet;
1630     }
1631
1632     OicParseQueryIter_t parseIter = { .attrPos=NULL };
1633     OicUuid_t subject = {.id={0}};
1634
1635     //Parsing REST query to get the subject
1636     ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1637     while (GetNextQuery(&parseIter))
1638     {
1639         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBOWNERID_NAME,
1640                 parseIter.attrLen) == 0)
1641         {
1642             if (0 == strncmp((const char*)parseIter.valPos, WILDCARD_RESOURCE_URI,
1643                              strlen(WILDCARD_RESOURCE_URI)))
1644             {
1645                 if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&WILDCARD_SUBJECT_ID))
1646                 {
1647                     ehRet = OC_EH_RESOURCE_DELETED;
1648                 }
1649             }
1650             else
1651             {
1652                 OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1653                 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1654
1655                 if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&subject))
1656                 {
1657                     ehRet = OC_EH_RESOURCE_DELETED;
1658                 }
1659             }
1660         }
1661     }
1662
1663     //Send response to request originator
1664     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1665                    OC_EH_OK : OC_EH_ERROR;
1666
1667     return ehRet;
1668 exit:
1669     return OC_EH_ERROR;
1670 }
1671 #endif //MULTIPLE_OWNER
1672
1673 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1674                                         OCEntityHandlerRequest * ehRequest,
1675                                         void* callbackParam)
1676 {
1677     (void)callbackParam;
1678     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1679
1680     if(NULL == ehRequest)
1681     {
1682         return ehRet;
1683     }
1684
1685     if (flag & OC_REQUEST_FLAG)
1686     {
1687         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1688
1689         switch (ehRequest->method)
1690         {
1691             case OC_REST_GET:
1692                 ehRet = HandleDoxmGetRequest(ehRequest);
1693                 break;
1694
1695             case OC_REST_POST:
1696                 ehRet = HandleDoxmPostRequest(ehRequest);
1697                 break;
1698
1699 #ifdef MULTIPLE_OWNER
1700             case OC_REST_DELETE:
1701                 ehRet = HandleDoxmDeleteRequest(ehRequest);
1702                 break;
1703 #endif //MULTIPLE_OWNER
1704
1705             default:
1706                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1707                                OC_EH_OK : OC_EH_ERROR;
1708                 break;
1709         }
1710     }
1711
1712     return ehRet;
1713 }
1714
1715 OCStackResult CreateDoxmResource()
1716 {
1717     OCStackResult ret = OCCreateResource(&gDoxmHandle,
1718                                          OIC_RSRC_TYPE_SEC_DOXM,
1719                                          OC_RSRVD_INTERFACE_DEFAULT,
1720                                          OIC_RSRC_DOXM_URI,
1721                                          DoxmEntityHandler,
1722                                          NULL,
1723                                          OC_SECURE |
1724                                          OC_DISCOVERABLE);
1725
1726     if (OC_STACK_OK != ret)
1727     {
1728         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1729         DeInitDoxmResource();
1730     }
1731     return ret;
1732 }
1733
1734 /**
1735  * Checks if DeviceID is generated during provisioning for the new device.
1736  * If DeviceID is NULL then generates the new DeviceID.
1737  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1738  */
1739 static OCStackResult CheckDeviceID()
1740 {
1741     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1742
1743     OCStackResult ret = OC_STACK_ERROR;
1744     bool validId = false;
1745
1746     if (!gDoxm)
1747     {
1748         OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
1749         return OC_STACK_INVALID_PARAM;
1750     }
1751
1752     for (uint8_t i = 0; i < UUID_LENGTH; i++)
1753     {
1754         if (gDoxm->deviceID.id[i] != 0)
1755         {
1756             validId = true;
1757             break;
1758         }
1759     }
1760
1761     if (!validId)
1762     {
1763         char* strUuid = NULL;
1764 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1765         //If seed value is exist, generate UUID using seed with SHA256
1766         if (0 != gUuidSeedSize)
1767         {
1768             uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1769             mbedtls_md_context_t sha_ctx;
1770             int mbedret = 1;
1771
1772             OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1773             OIC_LOG(DEBUG, TAG, "Seed value : ");
1774             OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1775
1776             mbedtls_md_init( &sha_ctx );
1777             mbedret = mbedtls_md_setup( &sha_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 );
1778             if (0 == mbedret)
1779             {
1780                 mbedtls_md_starts( &sha_ctx );
1781                 mbedtls_md_update( &sha_ctx, gUuidSeed, gUuidSeedSize);
1782                 mbedtls_md_finish(&sha_ctx, (unsigned char*)hashVal);
1783                 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1784                 ret = OC_STACK_OK;
1785             }
1786             else
1787             {
1788                 OIC_LOG_V(ERROR, TAG,  "mbedtls_md_setup() returned -0x%04x\n", -mbedret);
1789                 ret = OC_STACK_ERROR;
1790             }
1791             mbedtls_md_free( &sha_ctx );
1792         }
1793         else
1794         {
1795             if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
1796             {
1797                 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1798                 return OC_STACK_ERROR;
1799             }
1800             ret = OC_STACK_OK;
1801         }
1802 #else
1803         if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
1804         {
1805             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1806             return ret;
1807         }
1808         ret = OC_STACK_OK;
1809 #endif
1810
1811         if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1812         {
1813             OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1814             OICFree(strUuid);
1815         }
1816         else
1817         {
1818             OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1819         }
1820
1821
1822         if (!UpdatePersistentStorage(gDoxm))
1823         {
1824             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1825             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1826         }
1827     }
1828     else
1829     {
1830         ret = OC_STACK_OK;
1831     }
1832
1833     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
1834
1835     return ret;
1836 }
1837
1838 /**
1839  * Get the default value.
1840  *
1841  * @return the default value of doxm, @ref OicSecDoxm_t.
1842  */
1843 static OicSecDoxm_t* GetDoxmDefault()
1844 {
1845     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1846     return &gDefaultDoxm;
1847 }
1848
1849 const OicSecDoxm_t* GetDoxmResourceData()
1850 {
1851     return gDoxm;
1852 }
1853
1854 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1855 /**
1856  * Internal API to prepare MOT
1857  */
1858 static void PrepareMOT(const OicSecDoxm_t* doxm)
1859 {
1860     OIC_LOG(INFO, TAG, "IN PrepareMOT");
1861     VERIFY_NON_NULL(TAG, doxm, ERROR);
1862
1863     if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1864     {
1865         CAResult_t caRes = CA_STATUS_FAILED;
1866
1867         OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1868
1869         if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1870         {
1871             caRes = CAEnableAnonECDHCipherSuite(false);
1872             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1873             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1874
1875             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
1876             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1877 #ifdef __WITH_TLS__
1878             caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
1879             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1880 #endif
1881             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1882
1883             //Set the device id to derive temporal PSK
1884             SetUuidForPinBasedOxm(&doxm->deviceID);
1885         }
1886         else
1887         {
1888             OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1889             return;
1890         }
1891
1892         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1893     }
1894
1895     OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1896     return;
1897 exit:
1898     OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1899 }
1900 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1901
1902 OCStackResult InitDoxmResource()
1903 {
1904     OCStackResult ret = OC_STACK_ERROR;
1905
1906     gConfirmState = CONFIRM_STATE_READY;
1907     gConfirmMsgId = 0;
1908
1909     //Read DOXM resource from PS
1910     uint8_t *data = NULL;
1911     size_t size = 0;
1912     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1913     // If database read failed
1914     if (OC_STACK_OK != ret)
1915     {
1916        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1917     }
1918     if (data)
1919     {
1920        // Read DOXM resource from PS
1921        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1922     }
1923     /*
1924      * If SVR database in persistent storage got corrupted or
1925      * is not available for some reason, a default doxm is created
1926      * which allows user to initiate doxm provisioning again.
1927      */
1928      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1929     {
1930         gDoxm = GetDoxmDefault();
1931     }
1932
1933     //In case of the server is shut down unintentionally, we should initialize the owner
1934     if(gDoxm && (false == gDoxm->owned))
1935     {
1936         OicUuid_t emptyUuid = {.id={0}};
1937         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1938 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1939         InvokeOtmEventHandler(NULL, 0, NULL, OIC_OTM_READY);
1940 #endif
1941     }
1942
1943     ret = CheckDeviceID();
1944     if (ret == OC_STACK_OK)
1945     {
1946         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1947         //Instantiate 'oic.sec.doxm'
1948         ret = CreateDoxmResource();
1949     }
1950     else
1951     {
1952         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1953     }
1954     OICFree(data);
1955
1956 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1957     //if MOT is enabled, MOT should be prepared.
1958     if(gDoxm && gDoxm->owned)
1959     {
1960         PrepareMOT(gDoxm);
1961     }
1962 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1963
1964     return ret;
1965 }
1966
1967 OCStackResult DeInitDoxmResource()
1968 {
1969     OCStackResult ret = OCDeleteResource(gDoxmHandle);
1970     if (gDoxm  != &gDefaultDoxm)
1971     {
1972         DeleteDoxmBinData(gDoxm);
1973     }
1974     gDoxm = NULL;
1975
1976     if (OC_STACK_OK == ret)
1977     {
1978         return OC_STACK_OK;
1979     }
1980     else
1981     {
1982         return OC_STACK_ERROR;
1983     }
1984 }
1985
1986 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1987 {
1988     if (deviceID && gDoxm)
1989     {
1990        *deviceID = gDoxm->deviceID;
1991         return OC_STACK_OK;
1992     }
1993     return OC_STACK_ERROR;
1994 }
1995
1996 OCStackResult GetDoxmIsOwned(bool *isOwned)
1997 {
1998     if (isOwned && gDoxm)
1999     {
2000        *isOwned = gDoxm->owned;
2001         return OC_STACK_OK;
2002     }
2003     return OC_STACK_ERROR;
2004 }
2005
2006 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
2007 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
2008 {
2009     OIC_LOG_V(INFO, TAG, "In %s", __func__);
2010
2011     if (NULL == seed)
2012     {
2013         return OC_STACK_INVALID_PARAM;
2014     }
2015     if (MAX_UUID_SEED_SIZE < seedSize)
2016     {
2017         OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
2018         return OC_STACK_INVALID_PARAM;
2019     }
2020     if (MIN_UUID_SEED_SIZE > seedSize)
2021     {
2022         OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
2023         return OC_STACK_INVALID_PARAM;
2024     }
2025
2026     memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
2027     memcpy(gUuidSeed, seed, seedSize);
2028     gUuidSeedSize = seedSize;
2029
2030     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
2031
2032     return OC_STACK_OK;
2033 }
2034
2035 #endif
2036
2037 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
2038 {
2039     bool isOwnerUpdated = false;
2040     bool isRownerUpdated = false;
2041     if (NULL == deviceID)
2042     {
2043         return OC_STACK_INVALID_PARAM;
2044     }
2045     if (NULL == gDoxm)
2046     {
2047         OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
2048         return OC_STACK_NO_RESOURCE;
2049     }
2050
2051 #ifdef __WITH_DTLS__
2052     //for normal device.
2053     if (true == gDoxm->owned
2054             && memcmp(gEmptyUuid, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0
2055             && memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
2056     {
2057         OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
2058         OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
2059         return OC_STACK_ERROR;
2060     }
2061 #endif //__WITH_DTLS
2062
2063     //Save the previous UUID
2064     OicUuid_t prevUuid;
2065     memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
2066
2067     //Change the device UUID
2068     memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
2069
2070     //Change the owner ID if necessary
2071     if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2072     {
2073         memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
2074         isOwnerUpdated = true;
2075     }
2076     //Change the resource owner ID if necessary
2077     if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2078     {
2079         memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
2080         isRownerUpdated = true;
2081     }
2082     // TODO: T.B.D Change resource owner for pstat, acl and cred
2083
2084     //Update PS
2085     if (!UpdatePersistentStorage(gDoxm))
2086     {
2087         //revert UUID in case of PSI error
2088         memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(prevUuid.id));
2089         if (isOwnerUpdated)
2090         {
2091             memcpy(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id));
2092         }
2093         if (isRownerUpdated)
2094         {
2095             memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id));
2096         }
2097         // TODO: T.B.D Revert resource owner for pstat, acl and cred
2098
2099         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
2100         return OC_STACK_ERROR;
2101     }
2102     return OC_STACK_OK;
2103 }
2104
2105 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
2106 {
2107     OCStackResult retVal = OC_STACK_ERROR;
2108     if (gDoxm)
2109     {
2110         OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
2111             gDoxm->owned);
2112         if (gDoxm->owned)
2113         {
2114             *devownerid = gDoxm->owner;
2115             retVal = OC_STACK_OK;
2116         }
2117     }
2118     return retVal;
2119 }
2120
2121 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
2122 {
2123     OCStackResult retVal = OC_STACK_ERROR;
2124     if (gDoxm)
2125     {
2126         if( gDoxm->owned )
2127         {
2128             *rowneruuid = gDoxm->rownerID;
2129                     retVal = OC_STACK_OK;
2130         }
2131     }
2132     return retVal;
2133 }
2134
2135 #ifdef MULTIPLE_OWNER
2136 /**
2137  * Compare the UUID to SubOwner.
2138  *
2139  * @param[in] uuid device UUID
2140  *
2141  * @return true if context->subjectId exist subowner list, else false.
2142  */
2143 bool IsSubOwner(const OicUuid_t* uuid)
2144 {
2145     bool retVal = false;
2146
2147     if (NULL == uuid)
2148     {
2149         return retVal;
2150     }
2151
2152     if (gDoxm && gDoxm->subOwners)
2153     {
2154         if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
2155         {
2156             return false;
2157         }
2158
2159         OicSecSubOwner_t* subOwner = NULL;
2160         LL_FOREACH(gDoxm->subOwners, subOwner)
2161         {
2162             if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
2163             {
2164                 return true;
2165             }
2166         }
2167     }
2168     return retVal;
2169 }
2170 #endif //MULTIPLE_OWNER
2171
2172 OCStackResult SetMOTStatus(bool enable)
2173 {
2174     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2175 #ifdef MULTIPLE_OWNER
2176     OCStackResult ret = OC_STACK_NO_MEMORY;
2177     uint8_t *cborPayload = NULL;
2178     size_t size = 0;
2179     bool isDeallocateRequired = false;
2180
2181     VERIFY_NON_NULL(TAG, gDoxm, ERROR);
2182
2183     if (NULL == gDoxm->mom && !enable)
2184     {
2185         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2186         return OC_STACK_OK;
2187     }
2188
2189     if (NULL == gDoxm->mom)
2190     {
2191         gDoxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
2192         VERIFY_NON_NULL(TAG, gDoxm->mom, ERROR);
2193         isDeallocateRequired = true;
2194     }
2195
2196     gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
2197     gDoxm->oxmSel = OIC_PRECONFIG_PIN;
2198
2199     ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2200     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2201
2202     ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2203     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2204
2205     isDeallocateRequired = false;
2206
2207 exit:
2208     if (isDeallocateRequired)
2209     {
2210         OICFree(gDoxm->mom);
2211     }
2212     if (cborPayload)
2213     {
2214         OICFree(cborPayload);
2215     }
2216     OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
2217     return ret;
2218 #else
2219     OC_UNUSED(enable);
2220     OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2221     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2222     return OC_STACK_ERROR;
2223 #endif //MULTIPLE_OWNER
2224 }
2225
2226 OCStackResult RemoveSubOwner(const OicUuid_t* subOwner)
2227 {
2228     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2229 #ifdef MULTIPLE_OWNER
2230     OCStackResult ret = OC_STACK_ERROR;
2231     bool isDeleted = false;
2232
2233     if (NULL == subOwner)
2234     {
2235         OIC_LOG(ERROR, TAG, "Invalid sub owner UUID.");
2236         return OC_STACK_INVALID_PARAM;
2237     }
2238     if (NULL == gDoxm)
2239     {
2240         OIC_LOG(ERROR, TAG, "Doxm resource is NULL");
2241         return OC_STACK_NO_RESOURCE;
2242     }
2243     if ( NULL == gDoxm->subOwners)
2244     {
2245         OIC_LOG(WARNING, TAG, "Sub Owner list is empty.");
2246         return OC_STACK_ERROR;
2247     }
2248
2249     OicSecSubOwner_t* curSubOwner = NULL;
2250     OicSecSubOwner_t* tempSubOwner = NULL;
2251     LL_FOREACH_SAFE(gDoxm->subOwners, curSubOwner, tempSubOwner)
2252     {
2253         if (memcmp(curSubOwner->uuid.id, subOwner->id, sizeof(subOwner->id)) == 0 ||
2254             memcmp(WILDCARD_SUBJECT_ID.id, subOwner->id, sizeof(OicUuid_t)) == 0)
2255         {
2256             char* strUuid = NULL;
2257             ret = ConvertUuidToStr(&curSubOwner->uuid, &strUuid);
2258             if (OC_STACK_OK != ret)
2259             {
2260                 OIC_LOG_V(ERROR, TAG, "ConvertUuidToStr error : %d", ret);
2261                 break;
2262             }
2263
2264             OIC_LOG_V(INFO, TAG, "[%s] will be removed from sub owner list.", strUuid);
2265             LL_DELETE(gDoxm->subOwners, curSubOwner);
2266
2267             //Remove the cred for sub owner
2268             ret = RemoveCredential(&curSubOwner->uuid);
2269             if (OC_STACK_RESOURCE_DELETED != ret)
2270             {
2271                 OIC_LOG_V(WARNING, TAG, "RemoveCredential error for [%s] : %d", strUuid, ret);
2272                 break;
2273             }
2274
2275             // TODO: Remove the ACL for sub owner (Currently ACL is not required for sub-owner)
2276
2277             OICFree(strUuid);
2278
2279             isDeleted = true;
2280         }
2281     }
2282
2283     if (isDeleted)
2284     {
2285         //Update persistent storage
2286         if (UpdatePersistentStorage(gDoxm))
2287         {
2288             ret = OC_STACK_RESOURCE_DELETED;
2289         }
2290         else
2291         {
2292             OIC_LOG(ERROR, TAG, "UpdatePersistentStorage error");
2293             ret = OC_STACK_ERROR;
2294         }
2295     }
2296
2297     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2298     return ret;
2299 #else
2300     OC_UNUSED(subOwner);
2301     OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2302     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2303     return OC_STACK_ERROR;
2304 #endif //MULTIPLE_OWNER
2305
2306 }
2307
2308 OCStackResult SetNumberOfSubOwner(size_t numOfSubOwner)
2309 {
2310     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2311 #ifdef MULTIPLE_OWNER
2312     if (MAX_SUBOWNER_SIZE < numOfSubOwner || MIN_SUBOWNER_SIZE > numOfSubOwner)
2313     {
2314         OIC_LOG_V(ERROR, TAG, "Invalid number of sub owner : %d", numOfSubOwner);
2315         return OC_STACK_INVALID_PARAM;
2316     }
2317     gMaxSubOwnerSize = numOfSubOwner;
2318     OIC_LOG_V(DEBUG, TAG, "Number of SubOwner = %d", gMaxSubOwnerSize);
2319     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2320     return OC_STACK_OK;
2321 #else
2322     OC_UNUSED(numOfSubOwner);
2323     OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2324     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2325     return OC_STACK_ERROR;
2326 #endif //MULTIPLE_OWNER
2327 }
2328
2329 /**
2330  * Function to restore doxm resurce to initial status.
2331  * This function will use in case of error while ownership transfer
2332  */
2333 void RestoreDoxmToInitState()
2334 {
2335
2336     gConfirmState = CONFIRM_STATE_READY;
2337     gConfirmMsgId = 0;
2338
2339     if(gDoxm)
2340     {
2341         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
2342
2343         OicUuid_t emptyUuid = {.id={0}};
2344         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
2345         gDoxm->owned = false;
2346         gDoxm->oxmSel = OIC_JUST_WORKS;
2347
2348         if(!UpdatePersistentStorage(gDoxm))
2349         {
2350             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2351         }
2352     }
2353 }
2354
2355 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2356 {
2357     OCStackResult ret = OC_STACK_ERROR;
2358     uint8_t *cborPayload = NULL;
2359     size_t size = 0;
2360
2361     if(NULL == gDoxm)
2362     {
2363         ret = OC_STACK_NO_RESOURCE;
2364         return ret;
2365     }
2366
2367     if( newROwner && (false == gDoxm->owned) )
2368     {
2369         gDoxm->owned = true;
2370         memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2371         memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2372
2373         ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2374         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2375
2376         ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2377         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2378
2379         OICFree(cborPayload);
2380     }
2381
2382     return ret;
2383
2384 exit:
2385     OICFree(cborPayload);
2386     return ret;
2387 }
2388