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