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