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