Add API to set a seed value for UUID generation,
[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_NON_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_NON_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_NON_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_NON_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_NON_NULL(TAG, gDoxm, ERROR);
479         doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
480         VERIFY_NON_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_NON_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_NON_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_NON_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_NON_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_NON_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_NON_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_NON_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_NON_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_NON_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_NON_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                     //Save the owner's UUID to derive owner credential
1331                     memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1332                     gDoxm->oxmSel = newDoxm->oxmSel;
1333                     //Update new state in persistent storage
1334                     if (UpdatePersistentStorage(gDoxm))
1335                     {
1336                         ehRet = OC_EH_OK;
1337                     }
1338                     else
1339                     {
1340                         OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1341                         ehRet = OC_EH_ERROR;
1342                     }
1343                     CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1344                     VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1345                     OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1346
1347                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1348                     VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1349
1350                     //In case of Confirm Manufacturer Cert, get user confirmation
1351                     if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1352                         false == isDuplicatedMsg &&
1353                         memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1354                     {
1355                         if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1356                         {
1357                             ehRet = OC_EH_NOT_ACCEPTABLE;
1358                         }
1359                         else
1360                         {
1361                             ehRet = OC_EH_OK;
1362                         }
1363                     }
1364
1365
1366                 }
1367 #endif // __WITH_DTLS__ or __WITH_TLS__
1368             }
1369
1370             /*
1371              * When current state of the device is un-owned and Provisioning
1372              * Tool is attempting to change the state to 'Owned' with a
1373              * qualified value for the field 'Owner'
1374              */
1375             if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1376                     (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1377             {
1378                 //Change the SVR's resource owner as owner device.
1379                 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1380                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1381                 {
1382                     ehRet = OC_EH_ERROR;
1383                     goto exit;
1384                 }
1385                 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1386                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1387                 {
1388                     ehRet = OC_EH_ERROR;
1389                     goto exit;
1390                 }
1391                 ownerRes = SetCredRownerId(&gDoxm->owner);
1392                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1393                 {
1394                     ehRet = OC_EH_ERROR;
1395                     goto exit;
1396                 }
1397                 ownerRes = SetPstatRownerId(&gDoxm->owner);
1398                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1399                 {
1400                     ehRet = OC_EH_ERROR;
1401                     goto exit;
1402                 }
1403                 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1404                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1405                 {
1406                     ehRet = OC_EH_ERROR;
1407                     goto exit;
1408                 }
1409                 ownerRes = SetPconfRownerId(&gDoxm->owner);
1410                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1411                 {
1412                     ehRet = OC_EH_ERROR;
1413                     goto exit;
1414                 }
1415
1416                 gDoxm->owned = true;
1417                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1418
1419                 // Update new state in persistent storage
1420                 if (UpdatePersistentStorage(gDoxm))
1421                 {
1422                     //Update default ACE of security resource to prevent anonymous user access.
1423                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
1424                     {
1425                         ehRet = OC_EH_OK;
1426                     }
1427                     else
1428                     {
1429                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1430                         ehRet = OC_EH_ERROR;
1431                     }
1432                 }
1433                 else
1434                 {
1435                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1436                     ehRet = OC_EH_ERROR;
1437                 }
1438 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1439                 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1440                                             OIC_CON_MFG_CERT== gDoxm->oxmSel)
1441                 {
1442                     CAregisterPkixInfoHandler(GetPkixInfo);
1443                     CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1444                 }
1445 #endif // __WITH_DTLS__ or __WITH_TLS__
1446             }
1447         }
1448     }
1449
1450 exit:
1451     if(OC_EH_OK != ehRet)
1452     {
1453
1454         /*
1455          * If some error is occured while ownership transfer,
1456          * ownership transfer related resource should be revert back to initial status.
1457         */
1458         if(gDoxm)
1459         {
1460             if(!gDoxm->owned)
1461             {
1462                 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1463
1464                 if (!isDuplicatedMsg)
1465                 {
1466                     RestoreDoxmToInitState();
1467                     RestorePstatToInitState();
1468                     OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1469                 }
1470             }
1471         }
1472         else
1473         {
1474             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1475         }
1476     }
1477     else
1478     {
1479         previousMsgId = ehRequest->messageID;
1480     }
1481
1482     //Send payload to request originator
1483     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1484                    OC_EH_OK : OC_EH_ERROR;
1485
1486     DeleteDoxmBinData(newDoxm);
1487
1488     return ehRet;
1489 }
1490
1491 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1492                                         OCEntityHandlerRequest * ehRequest,
1493                                         void* callbackParam)
1494 {
1495     (void)callbackParam;
1496     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1497
1498     if(NULL == ehRequest)
1499     {
1500         return ehRet;
1501     }
1502
1503     if (flag & OC_REQUEST_FLAG)
1504     {
1505         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1506
1507         switch (ehRequest->method)
1508         {
1509             case OC_REST_GET:
1510                 ehRet = HandleDoxmGetRequest(ehRequest);
1511                 break;
1512
1513             case OC_REST_POST:
1514                 ehRet = HandleDoxmPostRequest(ehRequest);
1515                 break;
1516
1517             default:
1518                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1519                                OC_EH_OK : OC_EH_ERROR;
1520                 break;
1521         }
1522     }
1523
1524     return ehRet;
1525 }
1526
1527 OCStackResult CreateDoxmResource()
1528 {
1529     OCStackResult ret = OCCreateResource(&gDoxmHandle,
1530                                          OIC_RSRC_TYPE_SEC_DOXM,
1531                                          OC_RSRVD_INTERFACE_DEFAULT,
1532                                          OIC_RSRC_DOXM_URI,
1533                                          DoxmEntityHandler,
1534                                          NULL,
1535                                          OC_SECURE |
1536                                          OC_DISCOVERABLE);
1537
1538     if (OC_STACK_OK != ret)
1539     {
1540         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1541         DeInitDoxmResource();
1542     }
1543     return ret;
1544 }
1545
1546 /**
1547  * Checks if DeviceID is generated during provisioning for the new device.
1548  * If DeviceID is NULL then generates the new DeviceID.
1549  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1550  */
1551 static OCStackResult CheckDeviceID()
1552 {
1553     OCStackResult ret = OC_STACK_ERROR;
1554     bool validId = false;
1555
1556     for (uint8_t i = 0; i < UUID_LENGTH; i++)
1557     {
1558         if (gDoxm->deviceID.id[i] != 0)
1559         {
1560             validId = true;
1561             break;
1562         }
1563     }
1564
1565     if (!validId)
1566     {
1567         char* strUuid = NULL;
1568 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1569         //If seed value is exists, generate UUID using seed with SHA256
1570         if (0 != gUuidSeedSize)
1571         {
1572             uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1573             int mbedret = 0;
1574
1575             OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1576             OIC_LOG(DEBUG, TAG, "Seed value : ");
1577             OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1578
1579             mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1580                                  gUuidSeed, gUuidSeedSize, hashVal);
1581             if(0 == mbedret)
1582             {
1583                 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1584                 ret = OC_STACK_OK;
1585             }
1586             else
1587             {
1588                 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1589                 ret = OC_STACK_ERROR;
1590             }
1591         }
1592         else
1593         {
1594             if (!OCGenerateUuid(gDoxm->deviceID.id))
1595             {
1596                 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1597                 ret = OC_STACK_ERROR;
1598             }
1599             else
1600             {
1601                 ret = OC_STACK_OK;
1602             }
1603         }
1604 #else
1605         if (!OCGenerateUuid(gDoxm->deviceID.id))
1606         {
1607             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1608             ret = OC_STACK_ERROR;
1609         }
1610         else
1611         {
1612             ret = OC_STACK_OK;
1613         }
1614 #endif
1615
1616         if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1617         {
1618             OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1619             OICFree(strUuid);
1620         }
1621         else
1622         {
1623             OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1624         }
1625
1626
1627         if (!UpdatePersistentStorage(gDoxm))
1628         {
1629             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1630             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1631         }
1632     }
1633     else
1634     {
1635         ret = OC_STACK_OK;
1636     }
1637
1638     return ret;
1639 }
1640
1641 /**
1642  * Get the default value.
1643  *
1644  * @return the default value of doxm, @ref OicSecDoxm_t.
1645  */
1646 static OicSecDoxm_t* GetDoxmDefault()
1647 {
1648     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1649     return &gDefaultDoxm;
1650 }
1651
1652 const OicSecDoxm_t* GetDoxmResourceData()
1653 {
1654     return gDoxm;
1655 }
1656
1657 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1658 /**
1659  * Internal API to prepare MOT
1660  */
1661 static void PrepareMOT(const OicSecDoxm_t* doxm)
1662 {
1663     OIC_LOG(INFO, TAG, "IN PrepareMOT");
1664     VERIFY_NON_NULL(TAG, doxm, ERROR);
1665
1666     if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1667     {
1668         CAResult_t caRes = CA_STATUS_FAILED;
1669
1670         OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1671
1672         if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1673         {
1674             caRes = CAEnableAnonECDHCipherSuite(false);
1675             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1676             OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1677
1678             caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
1679             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1680 #ifdef __WITH_TLS__
1681             caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_TCP);
1682             VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1683 #endif
1684             OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1685
1686             //Set the device id to derive temporal PSK
1687             SetUuidForPinBasedOxm(&doxm->deviceID);
1688         }
1689         else
1690         {
1691             OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1692             return;
1693         }
1694
1695         CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1696     }
1697
1698     OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1699     return;
1700 exit:
1701     OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1702 }
1703 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1704
1705 OCStackResult InitDoxmResource()
1706 {
1707     OCStackResult ret = OC_STACK_ERROR;
1708
1709     //Read DOXM resource from PS
1710     uint8_t *data = NULL;
1711     size_t size = 0;
1712     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1713     // If database read failed
1714     if (OC_STACK_OK != ret)
1715     {
1716        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1717     }
1718     if (data)
1719     {
1720        // Read DOXM resource from PS
1721        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1722     }
1723     /*
1724      * If SVR database in persistent storage got corrupted or
1725      * is not available for some reason, a default doxm is created
1726      * which allows user to initiate doxm provisioning again.
1727      */
1728      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1729     {
1730         gDoxm = GetDoxmDefault();
1731     }
1732
1733     //In case of the server is shut down unintentionally, we should initialize the owner
1734     if(false == gDoxm->owned)
1735     {
1736         OicUuid_t emptyUuid = {.id={0}};
1737         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1738     }
1739
1740     ret = CheckDeviceID();
1741     if (ret == OC_STACK_OK)
1742     {
1743         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1744         //Instantiate 'oic.sec.doxm'
1745         ret = CreateDoxmResource();
1746     }
1747     else
1748     {
1749         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1750     }
1751     OICFree(data);
1752
1753 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1754     //if MOT is enabled, MOT should be prepared.
1755     if(gDoxm && gDoxm->owned)
1756     {
1757         PrepareMOT(gDoxm);
1758     }
1759 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1760
1761     return ret;
1762 }
1763
1764 OCStackResult DeInitDoxmResource()
1765 {
1766     OCStackResult ret = OCDeleteResource(gDoxmHandle);
1767     if (gDoxm  != &gDefaultDoxm)
1768     {
1769         DeleteDoxmBinData(gDoxm);
1770     }
1771     gDoxm = NULL;
1772
1773     if (OC_STACK_OK == ret)
1774     {
1775         return OC_STACK_OK;
1776     }
1777     else
1778     {
1779         return OC_STACK_ERROR;
1780     }
1781 }
1782
1783 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1784 {
1785     if (deviceID && gDoxm)
1786     {
1787        *deviceID = gDoxm->deviceID;
1788         return OC_STACK_OK;
1789     }
1790     return OC_STACK_ERROR;
1791 }
1792
1793 OCStackResult GetDoxmIsOwned(bool *isOwned)
1794 {
1795     if (isOwned && gDoxm)
1796     {
1797        *isOwned = gDoxm->owned;
1798         return OC_STACK_OK;
1799     }
1800     return OC_STACK_ERROR;
1801 }
1802
1803 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1804 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
1805 {
1806     OIC_LOG_V(INFO, TAG, "In %s", __func__);
1807
1808     if (NULL == seed)
1809     {
1810         return OC_STACK_INVALID_PARAM;
1811     }
1812     if (MAX_UUID_SEED_SIZE < seedSize)
1813     {
1814         OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
1815         return OC_STACK_INVALID_PARAM;
1816     }
1817     if (MIN_UUID_SEED_SIZE > seedSize)
1818     {
1819         OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
1820         return OC_STACK_INVALID_PARAM;
1821     }
1822
1823     memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
1824     memcpy(gUuidSeed, seed, seedSize);
1825     gUuidSeedSize = seedSize;
1826
1827     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1828
1829     return OC_STACK_OK;
1830 }
1831 #endif
1832
1833 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1834 {
1835     bool isPT = false;
1836
1837     if(NULL == deviceID)
1838     {
1839         return OC_STACK_INVALID_PARAM;
1840     }
1841     if(NULL == gDoxm)
1842     {
1843         OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1844         return OC_STACK_NO_RESOURCE;
1845     }
1846
1847     //Check the device's OTM state
1848
1849 #ifdef __WITH_DTLS__
1850     //for normal device.
1851     if(true == gDoxm->owned &&
1852        memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
1853     {
1854         OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1855         OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1856         return OC_STACK_ERROR;
1857     }
1858 #endif //__WITH_DTLS
1859
1860     //Save the previous UUID
1861     OicUuid_t tempUuid;
1862     memcpy(tempUuid.id, gDoxm->deviceID.id, sizeof(tempUuid.id));
1863
1864     //Change the UUID
1865     memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1866     if(isPT)
1867     {
1868         memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1869         memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1870     }
1871
1872     //Update PS
1873     if(!UpdatePersistentStorage(gDoxm))
1874     {
1875         //revert UUID in case of update error
1876         memcpy(gDoxm->deviceID.id, tempUuid.id, sizeof(tempUuid.id));
1877         if(isPT)
1878         {
1879             memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
1880             memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
1881         }
1882
1883         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
1884         return OC_STACK_ERROR;
1885     }
1886     return OC_STACK_OK;
1887 }
1888
1889 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1890 {
1891     OCStackResult retVal = OC_STACK_ERROR;
1892     if (gDoxm)
1893     {
1894         OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
1895             gDoxm->owned);
1896         if (gDoxm->owned)
1897         {
1898             *devownerid = gDoxm->owner;
1899             retVal = OC_STACK_OK;
1900         }
1901     }
1902     return retVal;
1903 }
1904
1905 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1906 {
1907     OCStackResult retVal = OC_STACK_ERROR;
1908     if (gDoxm)
1909     {
1910         if( gDoxm->owned )
1911         {
1912             *rowneruuid = gDoxm->rownerID;
1913                     retVal = OC_STACK_OK;
1914         }
1915     }
1916     return retVal;
1917 }
1918
1919 #ifdef MULTIPLE_OWNER
1920 /**
1921  * Compare the UUID to SubOwner.
1922  *
1923  * @param[in] uuid device UUID
1924  *
1925  * @return true if context->subjectId exist subowner list, else false.
1926  */
1927 bool IsSubOwner(const OicUuid_t* uuid)
1928 {
1929     bool retVal = false;
1930
1931     if (NULL == uuid)
1932     {
1933         return retVal;
1934     }
1935
1936     if (gDoxm && gDoxm->subOwners)
1937     {
1938         if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
1939         {
1940             return false;
1941         }
1942
1943         OicSecSubOwner_t* subOwner = NULL;
1944         LL_FOREACH(gDoxm->subOwners, subOwner)
1945         {
1946             if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
1947             {
1948                 return true;
1949             }
1950         }
1951     }
1952     return retVal;
1953 }
1954 #endif //MULTIPLE_OWNER
1955
1956 /**
1957  * Function to restore doxm resurce to initial status.
1958  * This function will use in case of error while ownership transfer
1959  */
1960 void RestoreDoxmToInitState()
1961 {
1962     if(gDoxm)
1963     {
1964         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
1965
1966         OicUuid_t emptyUuid = {.id={0}};
1967         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
1968         gDoxm->owned = false;
1969         gDoxm->oxmSel = OIC_JUST_WORKS;
1970
1971         if(!UpdatePersistentStorage(gDoxm))
1972         {
1973             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
1974         }
1975     }
1976 }
1977
1978 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
1979 {
1980     OCStackResult ret = OC_STACK_ERROR;
1981     uint8_t *cborPayload = NULL;
1982     size_t size = 0;
1983
1984     if(NULL == gDoxm)
1985     {
1986         ret = OC_STACK_NO_RESOURCE;
1987         return ret;
1988     }
1989
1990     if( newROwner && (false == gDoxm->owned) )
1991     {
1992         gDoxm->owned = true;
1993         memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
1994         memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
1995
1996         ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
1997         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1998
1999         ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2000         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2001
2002         OICFree(cborPayload);
2003     }
2004
2005     return ret;
2006
2007 exit:
2008     OICFree(cborPayload);
2009     return ret;
2010 }
2011