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