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