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