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