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