Merge remote-tracking branch 'origin/notification-service'
[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 "cainterface.h"
39 #include "ocserverrequest.h"
40 #include "resourcemanager.h"
41 #include "doxmresource.h"
42 #include "pstatresource.h"
43 #include "aclresource.h"
44 #include "amaclresource.h"
45 #include "pconfresource.h"
46 #include "dpairingresource.h"
47 #include "psinterface.h"
48 #include "srmresourcestrings.h"
49 #include "securevirtualresourcetypes.h"
50 #include "credresource.h"
51 #include "srmutility.h"
52 #include "pinoxmcommon.h"
53 #include "pmtypes.h"
54 #include "provisioningdatabasemanager.h"
55
56 #define TAG  "SRM-DOXM"
57
58 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
59  * The value of payload size is increased until reaching belox max cbor size. */
60 static const uint16_t CBOR_SIZE = 512;
61
62 /** Max cbor size payload. */
63 static const uint16_t CBOR_MAX_SIZE = 4400;
64
65 /** DOXM Map size - Number of mandatory items. */
66 static const uint8_t DOXM_MAP_SIZE = 9;
67
68 static OicSecDoxm_t        *gDoxm = NULL;
69 static OCResourceHandle    gDoxmHandle = NULL;
70
71 static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
72 static OicSecDoxm_t gDefaultDoxm =
73 {
74     NULL,                   /* OicUrn_t *oxmType */
75     0,                      /* size_t oxmTypeLen */
76     &gOicSecDoxmJustWorks,  /* uint16_t *oxm */
77     1,                      /* size_t oxmLen */
78     OIC_JUST_WORKS,         /* uint16_t oxmSel */
79     SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
80     false,                  /* bool owned */
81     {.id = {0}},            /* OicUuid_t deviceID */
82     false,                  /* bool dpc */
83     {.id = {0}},            /* OicUuid_t owner */
84     {.id = {0}},            /* OicUuid_t rownerID */
85 };
86
87 /**
88  * This method is internal method.
89  * the param roParsed is optionally used to know whether cborPayload has
90  * at least read only property value or not.
91  */
92 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
93                                 OicSecDoxm_t **doxm, bool *roParsed);
94
95 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
96 {
97     if (doxm)
98     {
99         //Clean oxmType
100         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
101         {
102             OICFree(doxm->oxmType[i]);
103         }
104         OICFree(doxm->oxmType);
105
106         //clean oxm
107         OICFree(doxm->oxm);
108
109         //Clean doxm itself
110         OICFree(doxm);
111     }
112 }
113
114 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
115                                 bool rwOnly)
116 {
117     if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
118     {
119         return OC_STACK_INVALID_PARAM;
120     }
121     size_t cborLen = *size;
122     if (0 == cborLen)
123     {
124         cborLen = CBOR_SIZE;
125     }
126     *payload = NULL;
127     *size = 0;
128
129     OCStackResult ret = OC_STACK_ERROR;
130
131     CborEncoder encoder;
132     CborEncoder doxmMap;
133     char* strUuid = NULL;
134
135     int64_t cborEncoderResult = CborNoError;
136     uint8_t mapSize = DOXM_MAP_SIZE;
137     if (doxm->oxmTypeLen > 0)
138     {
139         mapSize++;
140     }
141     if (doxm->oxmLen > 0)
142     {
143         mapSize++;
144     }
145
146     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
147     VERIFY_NON_NULL(TAG, outPayload, ERROR);
148     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
149
150     cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, mapSize);
151     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
152
153     //OxmType -- Not Mandatory
154     if (doxm->oxmTypeLen > 0)
155     {
156         CborEncoder oxmType;
157         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
158             strlen(OIC_JSON_OXM_TYPE_NAME));
159         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
160         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
161         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
162
163         for (size_t i = 0; i < doxm->oxmTypeLen; i++)
164         {
165             cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
166                 strlen(doxm->oxmType[i]));
167             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
168         }
169         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
170         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
171     }
172
173     //Oxm -- Not Mandatory
174     if (doxm->oxmLen > 0 && false == rwOnly)
175     {
176         CborEncoder oxm;
177         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
178             strlen(OIC_JSON_OXMS_NAME));
179         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
180         cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
181         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
182
183         for (size_t i = 0; i < doxm->oxmLen; i++)
184         {
185             cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
186             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
187         }
188         cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
189         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
190     }
191
192     //OxmSel -- Mandatory
193     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
194         strlen(OIC_JSON_OXM_SEL_NAME));
195     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
196     cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
197     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
198
199     //sct -- Mandatory
200     if (false == rwOnly)
201     {
202         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
203             strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
204         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
205         cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
206         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
207     }
208
209     //Owned -- Mandatory
210     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
211         strlen(OIC_JSON_OWNED_NAME));
212     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
213     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
214     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
215
216     if (false == rwOnly)
217     {
218         //DeviceId -- Mandatory
219         cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
220             strlen(OIC_JSON_DEVICE_ID_NAME));
221         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
222         ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
223         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
224         cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
225         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
226         OICFree(strUuid);
227         strUuid = NULL;
228     }
229
230     //devownerid -- Mandatory
231     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
232         strlen(OIC_JSON_DEVOWNERID_NAME));
233     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
234     ret = ConvertUuidToStr(&doxm->owner, &strUuid);
235     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
236     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
237     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
238     OICFree(strUuid);
239     strUuid = NULL;
240
241     //ROwner -- Mandatory
242     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
243         strlen(OIC_JSON_ROWNERID_NAME));
244     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
245     ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
246     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
247     cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
248     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
249     OICFree(strUuid);
250     strUuid = NULL;
251
252     //x.org.iotivity.dpc -- not Mandatory(vendor-specific), but this type is boolean, so instance always has a value.
253     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DPC_NAME,
254         strlen(OIC_JSON_DPC_NAME));
255     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Tag.");
256     cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->dpc);
257     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DPC Value.");
258
259     //RT -- Mandatory
260     CborEncoder rtArray;
261     cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
262             strlen(OIC_JSON_RT_NAME));
263     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
264     cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
265     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
266     for (size_t i = 0; i < 1; i++)
267     {
268         cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
269                 strlen(OIC_RSRC_TYPE_SEC_DOXM));
270         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
271     }
272     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
273     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
274
275     //IF-- Mandatory
276      CborEncoder ifArray;
277      cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
278              strlen(OIC_JSON_IF_NAME));
279      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
280      cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
281      VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
282     for (size_t i = 0; i < 1; i++)
283     {
284         cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
285                 strlen(OC_RSRVD_INTERFACE_DEFAULT));
286         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
287     }
288     cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
289     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
290
291     cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
292     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
293
294     if (CborNoError == cborEncoderResult)
295     {
296         *size = encoder.ptr - outPayload;
297         *payload = outPayload;
298         ret = OC_STACK_OK;
299     }
300 exit:
301     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
302     {
303         OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
304         // reallocate and try again!
305         OICFree(outPayload);
306         // Since the allocated initial memory failed, double the memory.
307         cborLen += encoder.ptr - encoder.end;
308         OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
309         cborEncoderResult = CborNoError;
310         ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
311         *size = cborLen;
312     }
313
314     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
315     {
316        OICFree(outPayload);
317        outPayload = NULL;
318        *payload = NULL;
319        *size = 0;
320        ret = OC_STACK_ERROR;
321     }
322
323     return ret;
324 }
325
326 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
327                                 OicSecDoxm_t **secDoxm)
328 {
329     return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
330 }
331
332 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
333                                 OicSecDoxm_t **secDoxm, bool *roParsed)
334 {
335     if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
336     {
337         return OC_STACK_INVALID_PARAM;
338     }
339
340     OCStackResult ret = OC_STACK_ERROR;
341     *secDoxm = NULL;
342
343     CborParser parser;
344     CborError cborFindResult = CborNoError;
345     char* strUuid = NULL;
346     size_t len = 0;
347     CborValue doxmCbor;
348
349     cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
350     CborValue doxmMap;
351     OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
352     VERIFY_NON_NULL(TAG, doxm, ERROR);
353
354     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
355     //OxmType -- not Mandatory
356     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
357     {
358         CborValue oxmType;
359
360         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
361         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.")
362         VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
363
364         doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
365         VERIFY_NON_NULL(TAG, doxm->oxmType, ERROR);
366
367         cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
368         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
369
370         int i = 0;
371         size_t len = 0;
372         while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
373         {
374             cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
375                                                         &len, NULL);
376             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.")
377             cborFindResult = cbor_value_advance(&oxmType);
378             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.")
379         }
380     }
381
382     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
383     //Oxm -- not Mandatory
384     if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
385     {
386         CborValue oxm;
387         cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
388         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.")
389         VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
390
391         doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
392         VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
393
394         cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
395         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
396
397         int i = 0;
398         while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
399         {
400             int tmp;
401
402             cborFindResult = cbor_value_get_int(&oxm, &tmp);
403             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
404             doxm->oxm[i++] = (OicSecOxm_t)tmp;
405             cborFindResult = cbor_value_advance(&oxm);
406             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
407         }
408
409         if (roParsed)
410         {
411             *roParsed = true;
412         }
413     }
414     else
415     {
416         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
417         doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
418         VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
419         doxm->oxmLen = gDoxm->oxmLen;
420         for (size_t i = 0; i < gDoxm->oxmLen; i++)
421         {
422             doxm->oxm[i] = gDoxm->oxm[i];
423         }
424     }
425
426     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
427     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
428     {
429         int oxmSel;
430
431         cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
432         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
433         doxm->oxmSel = (OicSecOxm_t)oxmSel;
434     }
435     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
436     {
437         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
438         doxm->oxmSel = gDoxm->oxmSel;
439     }
440
441     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
442     if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
443     {
444         int sct;
445
446         cborFindResult = cbor_value_get_int(&doxmMap, &sct);
447         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
448         doxm->sct = (OicSecCredType_t)sct;
449
450         if (roParsed)
451         {
452             *roParsed = true;
453         }
454     }
455     else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
456     {
457         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
458         doxm->sct = gDoxm->sct;
459     }
460
461     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
462     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
463     {
464         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
465         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
466     }
467     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
468     {
469         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
470         doxm->owned = gDoxm->owned;
471     }
472
473     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DPC_NAME, &doxmMap);
474     if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
475     {
476         cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->dpc);
477         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DPC Value.")
478     }
479     else // PUT/POST JSON may not have dpc so set it to the gDomx->dpc
480     {
481         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
482         doxm->dpc = gDoxm->dpc;
483     }
484
485     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
486     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
487     {
488         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
489         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
490         ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
491         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
492         OICFree(strUuid);
493         strUuid  = NULL;
494
495         if (roParsed)
496         {
497             *roParsed = true;
498         }
499     }
500     else
501     {
502         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
503         memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
504     }
505
506     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
507     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
508     {
509         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
510         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
511         ret = ConvertStrToUuid(strUuid , &doxm->owner);
512         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
513         OICFree(strUuid);
514         strUuid  = NULL;
515     }
516     else
517     {
518         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
519         memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
520     }
521
522     cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
523     if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
524     {
525         cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
526         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
527         ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
528         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
529         OICFree(strUuid);
530         strUuid  = NULL;
531     }
532     else
533     {
534         VERIFY_NON_NULL(TAG, gDoxm, ERROR);
535         memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
536     }
537
538     *secDoxm = doxm;
539     ret = OC_STACK_OK;
540
541 exit:
542     if (CborNoError != cborFindResult)
543     {
544         OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
545         DeleteDoxmBinData(doxm);
546         doxm = NULL;
547         *secDoxm = NULL;
548         ret = OC_STACK_ERROR;
549     }
550     return ret;
551 }
552
553 /**
554  * @todo document this function including why code might need to call this.
555  * The current suspicion is that it's not being called as much as it should.
556  */
557 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
558 {
559     bool bRet = false;
560
561     if (NULL != doxm)
562     {
563         // Convert Doxm data into CBOR for update to persistent storage
564         uint8_t *payload = NULL;
565         size_t size = 0;
566         OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
567         if (payload && (OC_STACK_OK == res)
568             && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
569         {
570                 bRet = true;
571         }
572         OICFree(payload);
573     }
574     else
575     {
576         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
577         {
578                 bRet = true;
579         }
580     }
581
582     return bRet;
583 }
584
585 static bool ValidateQuery(const char * query)
586 {
587     // Send doxm resource data if the state of doxm resource
588     // matches with the query parameters.
589     // else send doxm resource data as NULL
590     // TODO Remove this check and rely on Policy Engine
591     // and Provisioning Mode to enforce provisioning-state
592     // access rules. Eventually, the PE and PM code will
593     // not send a request to the /doxm Entity Handler at all
594     // if it should not respond.
595     OIC_LOG (DEBUG, TAG, "In ValidateQuery");
596     if(NULL == gDoxm)
597     {
598         return false;
599     }
600
601     bool bOwnedQry = false;         // does querystring contains 'owned' query ?
602     bool bOwnedMatch = false;       // does 'owned' query value matches with doxm.owned status?
603     bool bDeviceIDQry = false;      // does querystring contains 'deviceid' query ?
604     bool bDeviceIDMatch = false;    // does 'deviceid' query matches with doxm.deviceid ?
605     bool bInterfaceQry = false;      // does querystring contains 'if' query ?
606     bool bInterfaceMatch = false;    // does 'if' query matches with oic.if.baseline ?
607
608     OicParseQueryIter_t parseIter = {.attrPos = NULL};
609
610     ParseQueryIterInit((unsigned char*)query, &parseIter);
611
612     while (GetNextQuery(&parseIter))
613     {
614         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
615         {
616             bOwnedQry = true;
617             if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
618                     (gDoxm->owned))
619             {
620                 bOwnedMatch = true;
621             }
622             else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
623                     && (!gDoxm->owned))
624             {
625                 bOwnedMatch = true;
626             }
627         }
628
629         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
630         {
631             bDeviceIDQry = true;
632             OicUuid_t subject = {.id={0}};
633
634             memcpy(subject.id, parseIter.valPos, parseIter.valLen);
635             if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
636             {
637                 bDeviceIDMatch = true;
638             }
639         }
640
641         if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
642         {
643             bInterfaceQry = true;
644             if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
645             {
646                 bInterfaceMatch = true;
647             }
648             return (bInterfaceQry ? bInterfaceMatch: true);
649         }
650     }
651
652     return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
653 }
654
655 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
656 {
657     OCEntityHandlerResult ehRet = OC_EH_OK;
658
659     OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
660
661     //Checking if Get request is a query.
662     if (ehRequest->query)
663     {
664         OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
665         OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
666         if (!ValidateQuery(ehRequest->query))
667         {
668             ehRet = OC_EH_ERROR;
669         }
670     }
671
672     /*
673      * For GET or Valid Query request return doxm resource CBOR payload.
674      * For non-valid query return NULL json payload.
675      * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
676      * return valid doxm resource json.
677      */
678     uint8_t *payload = NULL;
679     size_t size = 0;
680
681     if (ehRet == OC_EH_OK)
682     {
683         if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
684         {
685             OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
686         }
687     }
688
689     OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
690     OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
691
692     // Send response payload to request originator
693     ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
694                    OC_EH_OK : OC_EH_ERROR;
695
696     OICFree(payload);
697
698     return ehRet;
699 }
700
701 static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest * ehRequest)
702 {
703     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing POST request");
704     OCEntityHandlerResult ehRet = OC_EH_ERROR;
705     OicUuid_t emptyOwner = {.id = {0} };
706     static uint16_t previousMsgId = 0;
707
708     /*
709      * Convert CBOR Doxm data into binary. This will also validate
710      * the Doxm data received.
711      */
712     OicSecDoxm_t *newDoxm = NULL;
713
714     if (ehRequest->payload)
715     {
716         uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
717         size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
718         bool roParsed = false;
719         OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
720         if (newDoxm && OC_STACK_OK == res)
721         {
722             // Check request on RO property
723             if (true == roParsed)
724             {
725                 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
726                 ehRet = OC_EH_NOT_ACCEPTABLE;
727                 goto exit;
728             }
729
730             // in owned state
731             if (true == gDoxm->owned)
732             {
733                 // update writable properties
734                 gDoxm->oxmSel = newDoxm->oxmSel;
735                 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
736                 memcpy(&(gDoxm->rownerID), &(newDoxm->rownerID), sizeof(OicUuid_t));
737
738                 if(gDoxm->owned != newDoxm->owned)
739                 {
740                     gDoxm->owned = newDoxm->owned;
741                 }
742
743                 //Update new state in persistent storage
744                 if (UpdatePersistentStorage(gDoxm) == true)
745                 {
746                     ehRet = OC_EH_OK;
747                 }
748                 else
749                 {
750                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
751                     ehRet = OC_EH_ERROR;
752                 }
753                 goto exit;
754             }
755
756             // in unowned state
757             if ((false == gDoxm->owned) && (false == newDoxm->owned))
758             {
759                 if (OIC_JUST_WORKS == newDoxm->oxmSel)
760                 {
761                     /*
762                      * If current state of the device is un-owned, enable
763                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
764                      * tool can initiate JUST_WORKS ownership transfer process.
765                      */
766                     if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
767                     {
768                         OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
769 #ifdef __WITH_DTLS__
770                         ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
771 #endif //__WITH_DTLS__
772                         goto exit;
773                     }
774                     else
775                     {
776 #ifdef __WITH_DTLS__
777                         //Save the owner's UUID to derive owner credential
778                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
779
780                         // Update new state in persistent storage
781                         if (true == UpdatePersistentStorage(gDoxm))
782                         {
783                             ehRet = OC_EH_OK;
784                         }
785                         else
786                         {
787                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
788                             ehRet = OC_EH_ERROR;
789                         }
790
791                         /*
792                          * Disable anonymous ECDH cipher in tinyDTLS since device is now
793                          * in owned state.
794                          */
795                         CAResult_t caRes = CA_STATUS_OK;
796                         caRes = CAEnableAnonECDHCipherSuite(false);
797                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
798                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
799
800 #ifdef __WITH_X509__
801 #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
802                         CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
803                                             ehRequest->devAddr.adapter);
804 #endif //__WITH_X509__
805 #endif //__WITH_DTLS__
806                     }
807                 }
808                 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
809                 {
810                     /*
811                      * If current state of the device is un-owned, enable
812                      * anonymous ECDH cipher in tinyDTLS so that Provisioning
813                      * tool can initiate JUST_WORKS ownership transfer process.
814                      */
815                     if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
816                     {
817                         gDoxm->oxmSel = newDoxm->oxmSel;
818                         //Update new state in persistent storage
819                         if ((UpdatePersistentStorage(gDoxm) == true))
820                         {
821                             ehRet = OC_EH_OK;
822                         }
823                         else
824                         {
825                             OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
826                             ehRet = OC_EH_ERROR;
827                         }
828
829 #ifdef __WITH_DTLS__
830                         CAResult_t caRes = CA_STATUS_OK;
831
832                         caRes = CAEnableAnonECDHCipherSuite(false);
833                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
834                         OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
835
836                         caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256,
837                                                     ehRequest->devAddr.adapter);
838                         VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
839
840                         char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
841                          //TODO ehRequest->messageID for copa over TCP always is null. Find reason why.
842                         if(ehRequest->devAddr.adapter == OC_ADAPTER_IP && previousMsgId != ehRequest->messageID)
843                         {
844                             if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
845                             {
846                                 //Set the device id to derive temporal PSK
847                                 SetUuidForRandomPinOxm(&gDoxm->deviceID);
848
849                                 /**
850                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
851                                  * Credential should not be saved into SVR.
852                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
853                                  */
854                                 caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm);
855                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
856                                 ehRet = OC_EH_OK;
857                             }
858                             else
859                             {
860                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
861                                 ehRet = OC_EH_ERROR;
862                             }
863                         }
864                         else
865                         {
866                             if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
867                             {
868                                 //Set the device id to derive temporal PSK
869                                 SetUuidForRandomPinOxm(&gDoxm->deviceID);
870
871                                 /**
872                                  * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
873                                  * Credential should not be saved into SVR.
874                                  * For this reason, use a temporary get_psk_info callback to random PIN OxM.
875                                  */
876 #ifdef __WITH_TLS__
877                                 caRes = CAregisterTlsCredentialsHandler(GetDtlsPskForRandomPinOxm);
878 #endif
879                                 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
880                                 ehRet = OC_EH_OK;
881                             }
882                             else
883                             {
884                                 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
885                                 ehRet = OC_EH_ERROR;
886                             }
887
888                         }
889 #endif //__WITH_DTLS__
890                     }
891                     else
892                     {
893 #ifdef __WITH_DTLS__
894                         //Save the owner's UUID to derive owner credential
895                         memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
896
897                         //Update new state in persistent storage
898                         if (UpdatePersistentStorage(gDoxm) == true)
899                         {
900                             ehRet = OC_EH_OK;
901                         }
902                         else
903                         {
904                             OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
905                             ehRet = OC_EH_ERROR;
906                         }
907 #endif
908                     }
909                 }
910             }
911
912             /*
913              * When current state of the device is un-owned and Provisioning
914              * Tool is attempting to change the state to 'Owned' with a
915              * qualified value for the field 'Owner'
916              */
917             if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
918                     (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
919             {
920                 //Change the SVR's resource owner as owner device.
921                 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
922                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
923                 {
924                     ehRet = OC_EH_ERROR;
925                     goto exit;
926                 }
927                 ownerRes = SetAmaclRownerId(&gDoxm->owner);
928                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
929                 {
930                     ehRet = OC_EH_ERROR;
931                     goto exit;
932                 }
933                 ownerRes = SetCredRownerId(&gDoxm->owner);
934                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
935                 {
936                     ehRet = OC_EH_ERROR;
937                     goto exit;
938                 }
939                 ownerRes = SetPstatRownerId(&gDoxm->owner);
940                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
941                 {
942                     ehRet = OC_EH_ERROR;
943                     goto exit;
944                 }
945                 ownerRes = SetDpairingRownerId(&gDoxm->owner);
946                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
947                 {
948                     ehRet = OC_EH_ERROR;
949                     goto exit;
950                 }
951                 ownerRes = SetPconfRownerId(&gDoxm->owner);
952                 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
953                 {
954                     ehRet = OC_EH_ERROR;
955                     goto exit;
956                 }
957
958                 gDoxm->owned = true;
959                 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
960
961                 // Update new state in persistent storage
962                 if (UpdatePersistentStorage(gDoxm))
963                 {
964                     //Update default ACE of security resource to prevent anonymous user access.
965                     if(OC_STACK_OK == UpdateDefaultSecProvACE())
966                     {
967                         ehRet = OC_EH_OK;
968                     }
969                     else
970                     {
971                         OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
972                         ehRet = OC_EH_ERROR;
973                     }
974                 }
975                 else
976                 {
977                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
978                     ehRet = OC_EH_ERROR;
979                 }
980             }
981         }
982     }
983
984 exit:
985     if(OC_EH_OK != ehRet)
986     {
987
988         /*
989          * If some error is occured while ownership transfer,
990          * ownership transfer related resource should be revert back to initial status.
991         */
992         if(gDoxm)
993         {
994             if(!gDoxm->owned && previousMsgId != ehRequest->messageID)
995             {
996                 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
997                                     "DOXM will be reverted.");
998                 RestoreDoxmToInitState();
999                 RestorePstatToInitState();
1000             }
1001         }
1002         else
1003         {
1004             OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1005         }
1006     }
1007     else
1008     {
1009         previousMsgId = ehRequest->messageID;
1010     }
1011
1012     //Send payload to request originator
1013     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1014                    OC_EH_OK : OC_EH_ERROR;
1015
1016     DeleteDoxmBinData(newDoxm);
1017
1018     return ehRet;
1019 }
1020
1021 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1022                                         OCEntityHandlerRequest * ehRequest,
1023                                         void* callbackParam)
1024 {
1025     (void)callbackParam;
1026     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1027
1028     if(NULL == ehRequest)
1029     {
1030         return ehRet;
1031     }
1032
1033     if (flag & OC_REQUEST_FLAG)
1034     {
1035         OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1036
1037         switch (ehRequest->method)
1038         {
1039             case OC_REST_GET:
1040                 ehRet = HandleDoxmGetRequest(ehRequest);
1041                 break;
1042
1043             case OC_REST_POST:
1044                 ehRet = HandleDoxmPostRequest(ehRequest);
1045                 break;
1046
1047             default:
1048                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1049                                OC_EH_OK : OC_EH_ERROR;
1050                 break;
1051         }
1052     }
1053
1054     return ehRet;
1055 }
1056
1057 OCStackResult CreateDoxmResource()
1058 {
1059     OCStackResult ret = OCCreateResource(&gDoxmHandle,
1060                                          OIC_RSRC_TYPE_SEC_DOXM,
1061                                          OC_RSRVD_INTERFACE_DEFAULT,
1062                                          OIC_RSRC_DOXM_URI,
1063                                          DoxmEntityHandler,
1064                                          NULL,
1065                                          OC_SECURE |
1066                                          OC_DISCOVERABLE);
1067
1068     if (OC_STACK_OK != ret)
1069     {
1070         OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1071         DeInitDoxmResource();
1072     }
1073     return ret;
1074 }
1075
1076 /**
1077  * Checks if DeviceID is generated during provisioning for the new device.
1078  * If DeviceID is NULL then generates the new DeviceID.
1079  * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1080  */
1081 static OCStackResult CheckDeviceID()
1082 {
1083     OCStackResult ret = OC_STACK_ERROR;
1084     bool validId = false;
1085     for (uint8_t i = 0; i < UUID_LENGTH; i++)
1086     {
1087         if (gDoxm->deviceID.id[i] != 0)
1088         {
1089             validId = true;
1090             break;
1091         }
1092     }
1093
1094     if (!validId)
1095     {
1096         if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
1097         {
1098             OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1099             return ret;
1100         }
1101         ret = OC_STACK_OK;
1102
1103         if (!UpdatePersistentStorage(gDoxm))
1104         {
1105             //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1106             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1107         }
1108     }
1109     else
1110     {
1111         ret = OC_STACK_OK;
1112     }
1113     return ret;
1114 }
1115
1116 /**
1117  * Get the default value.
1118  *
1119  * @return the default value of doxm, @ref OicSecDoxm_t.
1120  */
1121 static OicSecDoxm_t* GetDoxmDefault()
1122 {
1123     OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1124     return &gDefaultDoxm;
1125 }
1126
1127 const OicSecDoxm_t* GetDoxmResourceData()
1128 {
1129     return gDoxm;
1130 }
1131
1132 OCStackResult InitDoxmResource()
1133 {
1134     OCStackResult ret = OC_STACK_ERROR;
1135
1136     //Read DOXM resource from PS
1137     uint8_t *data = NULL;
1138     size_t size = 0;
1139     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1140     // If database read failed
1141     if (OC_STACK_OK != ret)
1142     {
1143        OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1144     }
1145     if (data)
1146     {
1147        // Read DOXM resource from PS
1148        ret = CBORPayloadToDoxm(data, size, &gDoxm);
1149     }
1150     /*
1151      * If SVR database in persistent storage got corrupted or
1152      * is not available for some reason, a default doxm is created
1153      * which allows user to initiate doxm provisioning again.
1154      */
1155      if ((OC_STACK_OK != ret) || !data || !gDoxm)
1156     {
1157         gDoxm = GetDoxmDefault();
1158     }
1159
1160     //In case of the server is shut down unintentionally, we should initialize the owner
1161     if(false == gDoxm->owned)
1162     {
1163         OicUuid_t emptyUuid = {.id={0}};
1164         memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1165     }
1166
1167     ret = CheckDeviceID();
1168     if (ret == OC_STACK_OK)
1169     {
1170         OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1171         //Instantiate 'oic.sec.doxm'
1172         ret = CreateDoxmResource();
1173     }
1174     else
1175     {
1176         OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1177     }
1178     OICFree(data);
1179     return ret;
1180 }
1181
1182 OCStackResult DeInitDoxmResource()
1183 {
1184     OCStackResult ret = OCDeleteResource(gDoxmHandle);
1185     if (gDoxm  != &gDefaultDoxm)
1186     {
1187         DeleteDoxmBinData(gDoxm);
1188     }
1189     gDoxm = NULL;
1190
1191     if (OC_STACK_OK == ret)
1192     {
1193         return OC_STACK_OK;
1194     }
1195     else
1196     {
1197         return OC_STACK_ERROR;
1198     }
1199 }
1200
1201 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1202 {
1203     if (deviceID && gDoxm)
1204     {
1205        *deviceID = gDoxm->deviceID;
1206         return OC_STACK_OK;
1207     }
1208     return OC_STACK_ERROR;
1209 }
1210
1211 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1212 {
1213     bool isPT = false;
1214
1215     if(NULL == deviceID)
1216     {
1217         return OC_STACK_INVALID_PARAM;
1218     }
1219     if(NULL == gDoxm)
1220     {
1221         OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1222         return OC_STACK_NO_RESOURCE;
1223     }
1224
1225     //Check the device's OTM state
1226
1227 #ifdef __WITH_DTLS__
1228     //for PT.
1229     if(true == gDoxm->owned &&
1230        memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) == 0)
1231     {
1232         OCUuidList_t* ownedDevices = NULL;
1233         size_t* ownedDevNum = 0;
1234
1235         if(OC_STACK_OK == PDMGetOwnedDevices(&ownedDevices, &ownedDevNum))
1236         {
1237             OCUuidList_t* temp1 = NULL;
1238             OCUuidList_t* temp2 = NULL;
1239             LL_FOREACH_SAFE(ownedDevices, temp1, temp2)
1240             {
1241                 LL_DELETE(ownedDevices, temp1);
1242                 OICFree(temp1);
1243             }
1244
1245             if(0 != ownedDevNum)
1246             {
1247                 OIC_LOG(ERROR, TAG, "This device has ownership for other device.");
1248                 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1249                 return OC_STACK_ERROR;
1250             }
1251         }
1252
1253         isPT = true;
1254     }
1255     //for normal device.
1256     else if(true == gDoxm->owned)
1257     {
1258         OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1259         OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1260         return OC_STACK_ERROR;
1261     }
1262 #endif //__WITH_DTLS
1263
1264     //Save the previous UUID
1265     OicUuid_t tempUuid;
1266     memcpy(tempUuid.id, gDoxm->deviceID.id, sizeof(tempUuid.id));
1267
1268     //Change the UUID
1269     memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1270     if(isPT)
1271     {
1272         memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1273         memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1274     }
1275
1276     //Update PS
1277     if(!UpdatePersistentStorage(gDoxm))
1278     {
1279         //revert UUID in case of update error
1280         memcpy(gDoxm->deviceID.id, tempUuid.id, sizeof(tempUuid.id));
1281         if(isPT)
1282         {
1283             memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
1284             memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
1285         }
1286
1287         OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
1288         return OC_STACK_ERROR;
1289     }
1290     return OC_STACK_OK;
1291 }
1292
1293 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1294 {
1295     OCStackResult retVal = OC_STACK_ERROR;
1296     if (gDoxm)
1297     {
1298         OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned =  %d.", \
1299             gDoxm->owned);
1300         if (gDoxm->owned)
1301         {
1302             *devownerid = gDoxm->owner;
1303             retVal = OC_STACK_OK;
1304         }
1305     }
1306     return retVal;
1307 }
1308
1309 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1310 {
1311     OCStackResult retVal = OC_STACK_ERROR;
1312     if (gDoxm)
1313     {
1314         if( gDoxm->owned )
1315         {
1316             *rowneruuid = gDoxm->rownerID;
1317                     retVal = OC_STACK_OK;
1318         }
1319     }
1320     return retVal;
1321 }
1322
1323 /**
1324  * Function to restore doxm resurce to initial status.
1325  * This function will use in case of error while ownership transfer
1326  */
1327 void RestoreDoxmToInitState()
1328 {
1329     if(gDoxm)
1330     {
1331         OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
1332
1333         OicUuid_t emptyUuid = {.id={0}};
1334         memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
1335         gDoxm->owned = false;
1336         gDoxm->oxmSel = OIC_JUST_WORKS;
1337
1338         if(!UpdatePersistentStorage(gDoxm))
1339         {
1340             OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
1341         }
1342     }
1343 }