1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include "iotivity_config.h"
21 #include "iotivity_debug.h"
30 #include "oic_malloc.h"
31 #include "payload_logging.h"
34 #include "ocpayload.h"
35 #include "ocpayloadcbor.h"
36 #include "cainterface.h"
37 #include "ocserverrequest.h"
38 #include "resourcemanager.h"
39 #include "doxmresource.h"
40 #include "pstatresource.h"
41 #include "aclresource.h"
42 #include "amaclresource.h"
43 #include "pconfresource.h"
44 #include "dpairingresource.h"
45 #include "psinterface.h"
46 #include "srmresourcestrings.h"
47 #include "securevirtualresourcetypes.h"
48 #include "credresource.h"
49 #include "srmutility.h"
50 #include "pinoxmcommon.h"
51 #include "oxmverifycommon.h"
52 #include "mbedtls/ssl_ciphersuites.h"
54 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
55 #include "mbedtls/md.h"
56 #include "pkix_interface.h"
59 #define TAG "OIC_SRM_DOXM"
60 #define CHAR_ZERO ('0')
62 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
63 * The value of payload size is increased until reaching belox max cbor size. */
64 static const uint16_t CBOR_SIZE = 512;
66 /** Max cbor size payload. */
67 static const uint16_t CBOR_MAX_SIZE = 4400;
69 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
70 /** MAX uuid seed size */
71 #define MAX_UUID_SEED_SIZE (64)
72 /** MIN uuid seed size */
73 #define MIN_UUID_SEED_SIZE (8)
75 /** Buffer to save the seed of device UUID */
76 static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
77 static size_t gUuidSeedSize = 0;
80 static OicSecDoxm_t *gDoxm = NULL;
81 static OCResourceHandle gDoxmHandle = NULL;
83 static OicSecOxm_t gDoxmDefaultOxm = OIC_RANDOM_DEVICE_PIN;
84 static OicSecDoxm_t gDefaultDoxm =
86 NULL, /* OicUrn_t *oxmType */
87 0, /* size_t oxmTypeLen */
88 &gDoxmDefaultOxm, /* uint16_t *oxm */
89 1, /* size_t oxmLen */
90 OIC_RANDOM_DEVICE_PIN, /* uint16_t oxmSel */
91 SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
92 false, /* bool owned */
93 {.id = {0}}, /* OicUuid_t deviceID */
95 {.id = {0}}, /* OicUuid_t owner */
97 NULL, /* OicSecSubOwner_t sub-owner list */
98 NULL, /* OicSecMomType_t multiple owner mode */
99 #endif //MULTIPLE_OWNER
100 {.id = {0}}, /* OicUuid_t rownerID */
104 * This method is internal method.
105 * the param roParsed is optionally used to know whether cborPayload has
106 * at least read only property value or not.
108 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
109 OicSecDoxm_t **doxm, bool *roParsed);
111 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
116 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
118 OICFree(doxm->oxmType[i]);
120 OICFree(doxm->oxmType);
125 #ifdef MULTIPLE_OWNER
129 //clean sub-owner list
130 if(NULL != doxm->subOwners)
132 OicSecSubOwner_t* subowner = NULL;
133 OicSecSubOwner_t* temp = NULL;
134 LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
136 LL_DELETE(doxm->subOwners, subowner);
140 #endif //MULTIPLE_OWNER
147 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
150 if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
152 return OC_STACK_INVALID_PARAM;
154 size_t cborLen = *size;
162 OCStackResult ret = OC_STACK_ERROR;
166 char* strUuid = NULL;
168 int64_t cborEncoderResult = CborNoError;
170 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
171 VERIFY_NOT_NULL(TAG, outPayload, ERROR);
172 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
174 cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
175 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
177 //OxmType -- Not Mandatory
178 if (doxm->oxmTypeLen > 0)
181 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
182 strlen(OIC_JSON_OXM_TYPE_NAME));
183 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
184 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
185 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
187 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
189 cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
190 strlen(doxm->oxmType[i]));
191 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
193 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
194 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
197 //Oxm -- Not Mandatory
198 if (doxm->oxmLen > 0 && false == rwOnly)
201 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
202 strlen(OIC_JSON_OXMS_NAME));
203 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
204 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
205 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
207 for (size_t i = 0; i < doxm->oxmLen; i++)
209 cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
210 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
212 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
213 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
216 //OxmSel -- Mandatory
217 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
218 strlen(OIC_JSON_OXM_SEL_NAME));
219 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
220 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
221 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
226 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
227 strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
228 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
229 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
230 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
234 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
235 strlen(OIC_JSON_OWNED_NAME));
236 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
237 cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
238 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
242 //DeviceId -- Mandatory
243 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
244 strlen(OIC_JSON_DEVICE_ID_NAME));
245 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
246 ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
247 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
248 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
249 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
254 #ifdef MULTIPLE_OWNER
255 //Device SubOwnerID -- Not Mandatory
258 size_t subOwnerLen = 0;
259 OicSecSubOwner_t* subOwner = NULL;
260 LL_FOREACH(doxm->subOwners, subOwner)
265 CborEncoder subOwners;
266 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
267 strlen(OIC_JSON_SUBOWNERID_NAME));
268 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
269 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
270 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
273 LL_FOREACH(doxm->subOwners, subOwner)
275 char* strUuid = NULL;
276 ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
277 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
278 cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
280 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
282 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
283 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
286 //Multiple Owner Mode -- Not Mandatory
289 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
290 strlen(OIC_JSON_MOM_NAME));
291 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
292 cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
293 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
295 #endif //MULTIPLE_OWNER
297 //devownerid -- Mandatory
298 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
299 strlen(OIC_JSON_DEVOWNERID_NAME));
300 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
301 ret = ConvertUuidToStr(&doxm->owner, &strUuid);
302 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
303 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
304 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
308 //ROwner -- Mandatory
309 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
310 strlen(OIC_JSON_ROWNERID_NAME));
311 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
312 ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
313 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
314 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
315 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
321 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
322 strlen(OIC_JSON_RT_NAME));
323 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
324 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
325 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
326 for (size_t i = 0; i < 1; i++)
328 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
329 strlen(OIC_RSRC_TYPE_SEC_DOXM));
330 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
332 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
333 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
337 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
338 strlen(OIC_JSON_IF_NAME));
339 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
340 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
341 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
342 for (size_t i = 0; i < 1; i++)
344 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
345 strlen(OC_RSRVD_INTERFACE_DEFAULT));
346 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
348 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
349 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
351 cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
352 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
354 if (CborNoError == cborEncoderResult)
356 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
357 *payload = outPayload;
361 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
363 OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
364 // reallocate and try again!
366 // Since the allocated initial memory failed, double the memory.
367 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
368 OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
369 cborEncoderResult = CborNoError;
370 ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
374 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
380 ret = OC_STACK_ERROR;
386 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
387 OicSecDoxm_t **secDoxm)
389 return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
392 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
393 OicSecDoxm_t **secDoxm, bool *roParsed)
395 if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
397 return OC_STACK_INVALID_PARAM;
400 OCStackResult ret = OC_STACK_ERROR;
404 CborError cborFindResult = CborNoError;
405 char* strUuid = NULL;
409 cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
411 OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
412 VERIFY_NOT_NULL(TAG, doxm, ERROR);
414 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
415 //OxmType -- not Mandatory
416 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
420 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
421 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
422 VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
424 doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
425 VERIFY_NOT_NULL(TAG, doxm->oxmType, ERROR);
427 cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
428 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
432 while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
434 cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
436 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
437 cborFindResult = cbor_value_advance(&oxmType);
438 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
442 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
443 //Oxm -- not Mandatory
444 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
447 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
448 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
449 VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
451 doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
452 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
454 cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
455 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
458 while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
462 cborFindResult = cbor_value_get_int(&oxm, &tmp);
463 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
464 doxm->oxm[i++] = (OicSecOxm_t)tmp;
465 cborFindResult = cbor_value_advance(&oxm);
466 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
476 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
477 doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
478 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
479 doxm->oxmLen = gDoxm->oxmLen;
480 for (size_t i = 0; i < gDoxm->oxmLen; i++)
482 doxm->oxm[i] = gDoxm->oxm[i];
486 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
487 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
491 cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
492 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
493 doxm->oxmSel = (OicSecOxm_t)oxmSel;
495 else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
497 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
498 doxm->oxmSel = gDoxm->oxmSel;
501 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
502 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
506 cborFindResult = cbor_value_get_int(&doxmMap, &sct);
507 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
508 doxm->sct = (OicSecCredType_t)sct;
515 else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
517 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
518 doxm->sct = gDoxm->sct;
521 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
522 if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
524 cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
525 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
527 else // PUT/POST JSON may not have owned so set it to the gDomx->owned
529 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
530 doxm->owned = gDoxm->owned;
533 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
534 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
536 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
537 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
538 ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
539 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
545 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
546 memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
549 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
550 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
552 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
553 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
554 ret = ConvertStrToUuid(strUuid , &doxm->owner);
555 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
561 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
562 memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
565 #ifdef MULTIPLE_OWNER
566 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
567 if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
570 cborFindResult = cbor_value_get_int(&doxmMap, &mode);
571 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
572 if(NULL == doxm->mom)
574 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
575 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
577 doxm->mom->mode = (OicSecMomType_t)mode;
579 else if(NULL != gDoxm && NULL != gDoxm->mom)
581 // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
582 if(NULL == doxm->mom)
584 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
585 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
587 doxm->mom->mode = gDoxm->mom->mode;
590 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
591 if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
593 size_t subOwnerLen = 0;
594 CborValue subOwnerCbor;
595 cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
596 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
597 VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
599 cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
600 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
602 while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
604 OCStackResult convertRes = OC_STACK_ERROR;
605 OicSecSubOwner_t* subOwner = NULL;
606 char* strUuid = NULL;
609 cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
610 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
612 subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
613 VERIFY_NOT_NULL(TAG, subOwner, ERROR);
615 convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
616 VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
617 subOwner->status = MOT_STATUS_DONE;
618 LL_APPEND(doxm->subOwners, subOwner);
620 cborFindResult = cbor_value_advance(&subOwnerCbor);
621 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
624 else if(NULL != gDoxm && NULL != gDoxm->subOwners)
626 // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
627 OicSecSubOwner_t* subOwnerItor = NULL;
628 LL_FOREACH(gDoxm->subOwners, subOwnerItor)
630 OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
631 VERIFY_NOT_NULL(TAG, subOwnerId, ERROR);
633 memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
634 subOwnerId->status = MOT_STATUS_DONE;
636 LL_APPEND(doxm->subOwners, subOwnerId);
639 #endif //MULTIPLE_OWNER
641 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
642 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
644 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
645 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
646 ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
647 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
653 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
654 memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
661 if (CborNoError != cborFindResult)
663 OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
664 DeleteDoxmBinData(doxm);
667 ret = OC_STACK_ERROR;
673 * @todo document this function including why code might need to call this.
674 * The current suspicion is that it's not being called as much as it should.
676 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
682 // Convert Doxm data into CBOR for update to persistent storage
683 uint8_t *payload = NULL;
685 OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
686 if (payload && (OC_STACK_OK == res)
687 && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
695 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
704 static bool ValidateQuery(const char * query)
706 // Send doxm resource data if the state of doxm resource
707 // matches with the query parameters.
708 // else send doxm resource data as NULL
709 // TODO Remove this check and rely on Policy Engine
710 // and Provisioning Mode to enforce provisioning-state
711 // access rules. Eventually, the PE and PM code will
712 // not send a request to the /doxm Entity Handler at all
713 // if it should not respond.
714 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
720 bool bOwnedQry = false; // does querystring contains 'owned' query ?
721 bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
722 bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
723 bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
724 bool bInterfaceQry = false; // does querystring contains 'if' query ?
725 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
726 #ifdef MULTIPLE_OWNER
727 bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
728 #endif //MULTIPLE_OWNER
730 OicParseQueryIter_t parseIter = {.attrPos = NULL};
732 ParseQueryIterInit((unsigned char*)query, &parseIter);
734 while (GetNextQuery(&parseIter))
736 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
739 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
744 else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
751 #ifdef MULTIPLE_OWNER
752 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
754 OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
755 if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
757 if(GetNextQuery(&parseIter))
759 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
761 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
771 #endif //MULTIPLE_OWNER
773 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
776 OicUuid_t subject = {.id={0}};
778 memcpy(subject.id, parseIter.valPos, parseIter.valLen);
779 if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
781 bDeviceIDMatch = true;
785 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
787 bInterfaceQry = true;
788 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
790 bInterfaceMatch = true;
792 return (bInterfaceQry ? bInterfaceMatch: true);
796 return ((bOwnedQry ? bOwnedMatch : true) &&
797 (bDeviceIDQry ? bDeviceIDMatch : true));
800 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
802 OCEntityHandlerResult ehRet = OC_EH_OK;
804 OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
806 //Checking if Get request is a query.
807 if (ehRequest->query)
809 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
810 OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
811 if (!ValidateQuery(ehRequest->query))
818 * For GET or Valid Query request return doxm resource CBOR payload.
819 * For non-valid query return NULL json payload.
820 * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
821 * return valid doxm resource json.
823 uint8_t *payload = NULL;
826 if (ehRet == OC_EH_OK)
828 if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
830 OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
834 OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
835 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
837 // Send response payload to request originator
838 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
839 OC_EH_OK : OC_EH_ERROR;
846 static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
851 dst->oxmSel = src->oxmSel;
854 memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
857 memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
860 memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
862 //Update owned status
863 if(dst->owned != src->owned)
865 dst->owned = src->owned;
868 #ifdef MULTIPLE_OWNER
871 OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
874 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
877 dst->mom->mode = src->mom->mode;
881 #endif //MULTIPLE_OWNER
885 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
886 #ifdef MULTIPLE_OWNER
888 * Callback function to handle MOT DTLS handshake result.
889 * @param[out] object remote device information.
890 * @param[out] errorInfo CA Error information.
892 void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
893 const CAErrorInfo_t *errorInfo)
895 OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
897 if(CA_STATUS_OK == errorInfo->result)
899 const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
900 if(authenticatedSubOwnerInfo)
902 if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
903 authenticatedSubOwnerInfo->identity.id_length))
905 OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
909 OicSecSubOwner_t* subOwnerInst = NULL;
910 LL_FOREACH(gDoxm->subOwners, subOwnerInst)
912 if(0 == memcmp(subOwnerInst->uuid.id,
913 authenticatedSubOwnerInfo->identity.id,
914 authenticatedSubOwnerInfo->identity.id_length))
920 if(NULL == subOwnerInst)
922 subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
925 char* strUuid = NULL;
926 memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
927 authenticatedSubOwnerInfo->identity.id_length);
928 if(OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
930 OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
933 OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
935 LL_APPEND(gDoxm->subOwners, subOwnerInst);
936 if(!UpdatePersistentStorage(gDoxm))
938 OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
945 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
947 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
950 OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
952 #endif //MULTIPLE_OWNER
953 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
956 * Function to validate oxmsel with oxms.
958 * @param[in] supportedMethods Array of supported methods
959 * @param[in] numberOfMethods number of supported methods
960 * @param[out] selectedMethod Selected methods
961 * @return TRUE on success
963 static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
964 size_t numberOfMethods, OicSecOxm_t *selectedMethod)
966 bool isValidOxmsel = false;
968 OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
969 if (numberOfMethods == 0 || !supportedMethods)
971 OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
972 return isValidOxmsel;
975 for (size_t i = 0; i < numberOfMethods; i++)
977 if (*selectedMethod == supportedMethods[i])
979 isValidOxmsel = true;
985 OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
986 return isValidOxmsel;
989 OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
991 return isValidOxmsel;
994 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
995 static void DoxmDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
997 OIC_LOG_V(DEBUG, TAG, "In %s(%p, %p)", __func__, endpoint, info);
999 if ((NULL != endpoint) && (NULL != info) && (CA_STATUS_OK == info->result))
1002 * Allow this OBT endpoint to bypass ACE checks for SVRs, while this
1003 * device is not yet owned.
1005 OC_VERIFY(CASetSecureEndpointAttribute(endpoint,
1006 CA_SECURE_ENDPOINT_ATTRIBUTE_ADMINISTRATOR));
1009 OIC_LOG_V(DEBUG, TAG, "Out %s(%p, %p)", __func__, endpoint, info);
1012 static void RegisterOTMSslHandshakeCallback(CAErrorCallback callback)
1014 OC_VERIFY(CA_STATUS_OK == CAregisterSslHandshakeCallback(callback));
1016 #endif // __WITH_DTLS__ or __WITH_TLS__
1018 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
1020 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
1021 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1022 OicUuid_t emptyOwner = {.id = {0} };
1023 static uint16_t previousMsgId = 0;
1024 bool isDuplicatedMsg = false;
1027 * Convert CBOR Doxm data into binary. This will also validate
1028 * the Doxm data received.
1030 OicSecDoxm_t *newDoxm = NULL;
1032 if (ehRequest->payload)
1034 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1035 size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1036 bool roParsed = false;
1037 OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
1038 if (newDoxm && OC_STACK_OK == res)
1041 * message ID is supported for CoAP over UDP only according to RFC 7252
1042 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1043 * In case of other transport adapter, duplicate message check is not required.
1045 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1046 previousMsgId == ehRequest->messageID)
1048 isDuplicatedMsg = true;
1051 // Check request on RO property
1052 if (true == roParsed)
1054 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
1055 ehRet = OC_EH_NOT_ACCEPTABLE;
1060 if (true == gDoxm->owned)
1062 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1064 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1065 ehRet = OC_EH_NOT_ACCEPTABLE;
1068 //Update gDoxm based on newDoxm
1069 updateWriteableProperty(newDoxm, gDoxm);
1071 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1072 #ifdef MULTIPLE_OWNER
1076 if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1078 CAResult_t caRes = CA_STATUS_FAILED;
1079 if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1081 caRes = CAEnableAnonECDHCipherSuite(false);
1082 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1083 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1085 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1086 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, ehRequest->devAddr.adapter);
1087 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1088 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1090 //Set the device id to derive temporal PSK
1091 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1095 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1098 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1102 //if MOM is disabled, revert the DTLS handshake callback
1103 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1105 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1110 if(newDoxm->subOwners)
1112 OicSecSubOwner_t* subowner = NULL;
1113 OicSecSubOwner_t* temp = NULL;
1115 OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1117 if(gDoxm->subOwners)
1119 LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1121 LL_DELETE(gDoxm->subOwners, subowner);
1128 LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1130 LL_DELETE(newDoxm->subOwners, subowner);
1131 LL_APPEND(gDoxm->subOwners, subowner);
1134 #endif //MULTIPLE_OWNER
1135 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1137 //Update new state in persistent storage
1138 if (UpdatePersistentStorage(gDoxm) == true)
1144 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1145 ehRet = OC_EH_ERROR;
1151 if ((false == gDoxm->owned) && (false == newDoxm->owned))
1153 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1155 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1156 ehRet = OC_EH_NOT_ACCEPTABLE;
1160 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1163 * If current state of the device is un-owned, enable
1164 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1165 * tool can initiate JUST_WORKS ownership transfer process.
1167 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1169 gDoxm->oxmSel = newDoxm->oxmSel;
1170 //Update new state in persistent storage
1171 if ((UpdatePersistentStorage(gDoxm) == true))
1177 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1178 ehRet = OC_EH_ERROR;
1181 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1182 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1183 OIC_LOG(INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
1184 ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1185 #endif // __WITH_DTLS__ or __WITH_TLS__
1190 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1191 //Save the owner's UUID to derive owner credential
1192 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1194 // Update new state in persistent storage
1195 if (true == UpdatePersistentStorage(gDoxm))
1201 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1202 ehRet = OC_EH_ERROR;
1207 * Disable anonymous ECDH cipher in tinyDTLS since device is now
1210 RegisterOTMSslHandshakeCallback(NULL);
1211 CAResult_t caRes = CA_STATUS_OK;
1212 caRes = CAEnableAnonECDHCipherSuite(false);
1213 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1214 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1216 //In case of Mutual Verified Just-Works, verify mutualVerifNum
1217 if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1218 false == isDuplicatedMsg)
1220 uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1221 uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1222 OicUuid_t deviceID = {.id = {0}};
1224 //Generate mutualVerifNum
1225 OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1227 char label[LABEL_LEN] = {0};
1228 snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1229 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1231 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1232 ehRet = OC_EH_ERROR;
1237 CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1240 gDoxm->owner.id, sizeof(gDoxm->owner.id),
1241 gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1242 preMutualVerifNum, OWNER_PSK_LENGTH_128);
1243 if (CA_STATUS_OK != pskRet)
1245 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1246 ehRet = OC_EH_ERROR;
1251 memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1252 sizeof(mutualVerifNum));
1254 //Wait for user confirmation
1255 if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1257 ehRet = OC_EH_NOT_ACCEPTABLE;
1265 #endif // __WITH_DTLS__ or __WITH_TLS__
1268 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1271 * If current state of the device is un-owned, enable
1272 * ECDHE_PSK cipher so that the Provisioning tool can
1273 * initiate the ownership transfer.
1275 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1277 gDoxm->oxmSel = newDoxm->oxmSel;
1278 //Update new state in persistent storage
1279 if ((UpdatePersistentStorage(gDoxm) == true))
1285 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1286 ehRet = OC_EH_ERROR;
1289 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1290 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1291 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1292 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1294 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1295 caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1296 ehRequest->devAddr.adapter);
1297 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1299 if (!isDuplicatedMsg)
1301 char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1302 if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1304 //Set the device id to derive temporal PSK
1305 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1308 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1309 * Credential should not be saved into SVR.
1310 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1312 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1313 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1318 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1319 ehRet = OC_EH_ERROR;
1322 #endif // __WITH_DTLS__ or __WITH_TLS__
1324 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1327 //Save the owner's UUID to derive owner credential
1328 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1330 //Update new state in persistent storage
1331 if (UpdatePersistentStorage(gDoxm) == true)
1337 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1338 ehRet = OC_EH_ERROR;
1341 #endif // __WITH_DTLS__ or __WITH_TLS__
1343 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1344 else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1346 //In case of Confirm Manufacturer Cert, get user confirmation
1347 if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1348 false == isDuplicatedMsg &&
1349 memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1351 if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1353 ehRet = OC_EH_NOT_ACCEPTABLE;
1362 //Save the owner's UUID to derive owner credential
1363 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1364 gDoxm->oxmSel = newDoxm->oxmSel;
1365 //Update new state in persistent storage
1366 if (UpdatePersistentStorage(gDoxm))
1372 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1373 ehRet = OC_EH_ERROR;
1376 RegisterOTMSslHandshakeCallback(NULL);
1377 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1378 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1379 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1381 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1382 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1384 #endif // __WITH_DTLS__ or __WITH_TLS__
1388 * When current state of the device is un-owned and Provisioning
1389 * Tool is attempting to change the state to 'Owned' with a
1390 * qualified value for the field 'Owner'
1392 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1393 (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1395 //Change the SVR's resource owner as owner device.
1396 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1397 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1399 ehRet = OC_EH_ERROR;
1402 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1403 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1405 ehRet = OC_EH_ERROR;
1408 ownerRes = SetCredRownerId(&gDoxm->owner);
1409 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1411 ehRet = OC_EH_ERROR;
1414 ownerRes = SetPstatRownerId(&gDoxm->owner);
1415 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1417 ehRet = OC_EH_ERROR;
1420 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1421 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1423 ehRet = OC_EH_ERROR;
1426 ownerRes = SetPconfRownerId(&gDoxm->owner);
1427 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1429 ehRet = OC_EH_ERROR;
1433 gDoxm->owned = true;
1434 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1436 // Update new state in persistent storage
1437 if (UpdatePersistentStorage(gDoxm))
1439 //Update default ACE of security resource to prevent anonymous user access.
1440 if(OC_STACK_OK == UpdateDefaultSecProvACE())
1446 OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1447 ehRet = OC_EH_ERROR;
1452 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1453 ehRet = OC_EH_ERROR;
1455 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1456 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1457 OIC_CON_MFG_CERT== gDoxm->oxmSel)
1459 CAregisterPkixInfoHandler(GetPkixInfo);
1460 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1462 #endif // __WITH_DTLS__ or __WITH_TLS__
1468 if(OC_EH_OK != ehRet)
1472 * If some error is occured while ownership transfer,
1473 * ownership transfer related resource should be revert back to initial status.
1479 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1481 if (!isDuplicatedMsg)
1483 RestoreDoxmToInitState();
1484 RestorePstatToInitState();
1485 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1491 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1496 previousMsgId = ehRequest->messageID;
1499 //Send payload to request originator
1500 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1501 OC_EH_OK : OC_EH_ERROR;
1503 DeleteDoxmBinData(newDoxm);
1508 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1509 OCEntityHandlerRequest * ehRequest,
1510 void* callbackParam)
1512 (void)callbackParam;
1513 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1515 if(NULL == ehRequest)
1520 if (flag & OC_REQUEST_FLAG)
1522 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1524 switch (ehRequest->method)
1527 ehRet = HandleDoxmGetRequest(ehRequest);
1531 ehRet = HandleDoxmPostRequest(ehRequest);
1535 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1536 OC_EH_OK : OC_EH_ERROR;
1544 OCStackResult CreateDoxmResource()
1546 OCStackResult ret = OCCreateResource(&gDoxmHandle,
1547 OIC_RSRC_TYPE_SEC_DOXM,
1548 OC_RSRVD_INTERFACE_DEFAULT,
1555 if (OC_STACK_OK != ret)
1557 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1558 DeInitDoxmResource();
1564 * Checks if DeviceID is generated during provisioning for the new device.
1565 * If DeviceID is NULL then generates the new DeviceID.
1566 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1568 static OCStackResult CheckDeviceID()
1570 OCStackResult ret = OC_STACK_ERROR;
1571 bool validId = false;
1573 for (uint8_t i = 0; i < UUID_LENGTH; i++)
1575 if (gDoxm->deviceID.id[i] != 0)
1584 char* strUuid = NULL;
1585 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1586 //If seed value is exists, generate UUID using seed with SHA256
1587 if (0 != gUuidSeedSize)
1589 uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1592 OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1593 OIC_LOG(DEBUG, TAG, "Seed value : ");
1594 OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1596 mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1597 gUuidSeed, gUuidSeedSize, hashVal);
1600 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1605 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1606 ret = OC_STACK_ERROR;
1611 if (!OCGenerateUuid(gDoxm->deviceID.id))
1613 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1614 ret = OC_STACK_ERROR;
1622 if (!OCGenerateUuid(gDoxm->deviceID.id))
1624 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1625 ret = OC_STACK_ERROR;
1633 if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1635 OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1640 OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1644 if (!UpdatePersistentStorage(gDoxm))
1646 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1647 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1659 * Get the default value.
1661 * @return the default value of doxm, @ref OicSecDoxm_t.
1663 static OicSecDoxm_t* GetDoxmDefault()
1665 OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1666 return &gDefaultDoxm;
1669 const OicSecDoxm_t* GetDoxmResourceData()
1674 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1676 * Internal API to prepare MOT
1678 static void PrepareMOT(const OicSecDoxm_t* doxm)
1680 OIC_LOG(INFO, TAG, "IN PrepareMOT");
1681 VERIFY_NOT_NULL(TAG, doxm, ERROR);
1683 if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1685 CAResult_t caRes = CA_STATUS_FAILED;
1687 OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1689 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1691 caRes = CAEnableAnonECDHCipherSuite(false);
1692 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1693 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1695 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1696 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
1697 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1699 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
1700 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1702 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1704 //Set the device id to derive temporal PSK
1705 SetUuidForPinBasedOxm(&doxm->deviceID);
1709 OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1713 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1716 OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1719 OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1721 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1723 OCStackResult InitDoxmResource()
1725 OCStackResult ret = OC_STACK_ERROR;
1727 //Read DOXM resource from PS
1728 uint8_t *data = NULL;
1730 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1731 // If database read failed
1732 if (OC_STACK_OK != ret)
1734 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1738 // Read DOXM resource from PS
1739 ret = CBORPayloadToDoxm(data, size, &gDoxm);
1742 * If SVR database in persistent storage got corrupted or
1743 * is not available for some reason, a default doxm is created
1744 * which allows user to initiate doxm provisioning again.
1746 if ((OC_STACK_OK != ret) || !data || !gDoxm)
1748 gDoxm = GetDoxmDefault();
1751 //In case of the server is shut down unintentionally, we should initialize the owner
1752 if(gDoxm && (false == gDoxm->owned))
1754 OicUuid_t emptyUuid = {.id={0}};
1755 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1758 ret = CheckDeviceID();
1759 if (ret == OC_STACK_OK)
1761 OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1762 //Instantiate 'oic.sec.doxm'
1763 ret = CreateDoxmResource();
1767 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1771 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1772 //if MOT is enabled, MOT should be prepared.
1773 if(gDoxm && gDoxm->owned)
1777 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1782 OCStackResult DeInitDoxmResource()
1784 OCStackResult ret = OCDeleteResource(gDoxmHandle);
1785 if (gDoxm != &gDefaultDoxm)
1787 DeleteDoxmBinData(gDoxm);
1791 if (OC_STACK_OK == ret)
1797 return OC_STACK_ERROR;
1801 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1803 if (deviceID && gDoxm)
1805 *deviceID = gDoxm->deviceID;
1808 return OC_STACK_ERROR;
1811 OCStackResult GetDoxmIsOwned(bool *isOwned)
1813 if (isOwned && gDoxm)
1815 *isOwned = gDoxm->owned;
1818 return OC_STACK_ERROR;
1821 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1822 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
1824 OIC_LOG_V(INFO, TAG, "In %s", __func__);
1828 return OC_STACK_INVALID_PARAM;
1830 if (MAX_UUID_SEED_SIZE < seedSize)
1832 OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
1833 return OC_STACK_INVALID_PARAM;
1835 if (MIN_UUID_SEED_SIZE > seedSize)
1837 OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
1838 return OC_STACK_INVALID_PARAM;
1841 memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
1842 memcpy(gUuidSeed, seed, seedSize);
1843 gUuidSeedSize = seedSize;
1845 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1851 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1853 bool isOwnerUpdated = false;
1854 bool isRownerUpdated = false;
1855 if (NULL == deviceID)
1857 return OC_STACK_INVALID_PARAM;
1861 OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1862 return OC_STACK_NO_RESOURCE;
1865 #ifdef __WITH_DTLS__
1866 //for normal device.
1867 if (true == gDoxm->owned &&
1868 memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
1870 OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1871 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1872 return OC_STACK_ERROR;
1874 #endif //__WITH_DTLS
1876 //Save the previous UUID
1878 memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
1880 //Change the device UUID
1881 memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1883 //Change the owner ID if necessary
1884 if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
1886 memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1887 isOwnerUpdated = true;
1889 //Change the resource owner ID if necessary
1890 if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
1892 memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1893 isRownerUpdated = true;
1895 // TODO: T.B.D Change resource owner for pstat, acl and cred
1898 if (!UpdatePersistentStorage(gDoxm))
1900 //revert UUID in case of PSI error
1901 memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(prevUuid.id));
1904 memcpy(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id));
1906 if (isRownerUpdated)
1908 memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id));
1910 // TODO: T.B.D Revert resource owner for pstat, acl and cred
1912 OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
1913 return OC_STACK_ERROR;
1918 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1920 OCStackResult retVal = OC_STACK_ERROR;
1923 OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned = %d.", \
1927 *devownerid = gDoxm->owner;
1928 retVal = OC_STACK_OK;
1934 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1936 OCStackResult retVal = OC_STACK_ERROR;
1941 *rowneruuid = gDoxm->rownerID;
1942 retVal = OC_STACK_OK;
1948 #ifdef MULTIPLE_OWNER
1950 * Compare the UUID to SubOwner.
1952 * @param[in] uuid device UUID
1954 * @return true if context->subjectId exist subowner list, else false.
1956 bool IsSubOwner(const OicUuid_t* uuid)
1958 bool retVal = false;
1965 if (gDoxm && gDoxm->subOwners)
1967 if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
1972 OicSecSubOwner_t* subOwner = NULL;
1973 LL_FOREACH(gDoxm->subOwners, subOwner)
1975 if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
1983 #endif //MULTIPLE_OWNER
1986 * Function to restore doxm resurce to initial status.
1987 * This function will use in case of error while ownership transfer
1989 void RestoreDoxmToInitState()
1993 OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
1995 OicUuid_t emptyUuid = {.id={0}};
1996 memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
1997 gDoxm->owned = false;
1998 gDoxm->oxmSel = OIC_JUST_WORKS;
2000 if(!UpdatePersistentStorage(gDoxm))
2002 OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2007 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2009 OCStackResult ret = OC_STACK_ERROR;
2010 uint8_t *cborPayload = NULL;
2015 ret = OC_STACK_NO_RESOURCE;
2019 if( newROwner && (false == gDoxm->owned) )
2021 gDoxm->owned = true;
2022 memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2023 memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2025 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2026 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2028 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2029 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2031 OICFree(cborPayload);
2037 OICFree(cborPayload);
2041 #ifdef MULTIPLE_OWNER
2042 /** This function checks if two sets of /oic/sec/doxm MOT-specific properties are identical.
2044 * @param doxm1 is a pointer to the first @ref OicSecDoxm_t data.
2045 * @param doxm2 is a pointer to the second @ref OicSecDoxm_t data.
2047 * @return true if all of the properties are identical, else false.
2049 static bool AreDoxmBinMOTPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2051 //Compare the subOwners lists.
2052 OicSecSubOwner_t* subOwner1 = doxm1->subOwners;
2053 OicSecSubOwner_t* subOwner2 = doxm2->subOwners;
2057 if ((NULL == subOwner1) && (NULL == subOwner2))
2059 //Reached the end of both lists, so the two lists were identical.
2063 if ((NULL != subOwner1) && (NULL != subOwner2))
2065 if (0 != memcmp(&subOwner1->uuid, &subOwner2->uuid, sizeof(subOwner1->uuid)))
2067 OIC_LOG_V(ERROR, TAG, "%s: subOwner uuid mismatch", __func__);
2071 if (subOwner1->status != subOwner2->status)
2073 OIC_LOG_V(ERROR, TAG, "%s: subOwner status mismatch: (%u, %u)",
2074 __func__, (uint32_t)subOwner1->status, (uint32_t)subOwner2->status);
2078 //Go to the next elements from the two lists.
2079 subOwner1 = subOwner1->next;
2080 subOwner2 = subOwner2->next;
2084 OIC_LOG_V(ERROR, TAG, "%s: subOwner list length mismatch", __func__);
2088 // Compare the mom values.
2089 if (NULL == doxm1->mom)
2091 if (NULL != doxm2->mom)
2093 OIC_LOG_V(ERROR, TAG, "%s: doxm1->mom is NULL", __func__);
2100 if (NULL == doxm2->mom)
2102 OIC_LOG_V(ERROR, TAG, "%s: doxm2->mom is NULL", __func__);
2106 if (doxm1->mom->mode != doxm2->mom->mode)
2108 OIC_LOG_V(ERROR, TAG, "%s: mom->mode mismatch: (%u, %u)",
2109 __func__, (uint32_t)doxm1->mom->mode, (uint32_t)doxm2->mom->mode);
2115 #endif //#ifdef MULTIPLE_OWNER
2117 bool AreDoxmBinPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2119 if (NULL == doxm1 || NULL == doxm2)
2121 OIC_LOG_V(ERROR, TAG, "%s: unxpected NULL doxm pointer", __func__);
2125 //Compare the contents of the oxmType array and its length oxmTypeLen.
2126 size_t arrayLength = doxm1->oxmTypeLen;
2128 if (arrayLength != doxm2->oxmTypeLen)
2130 OIC_LOG_V(ERROR, TAG, "%s: oxmTypeLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
2131 __func__, arrayLength, doxm2->oxmTypeLen);
2135 for (size_t i = 0; i < arrayLength; i++)
2137 if (NULL == doxm1->oxmType[i] || NULL == doxm2->oxmType[i])
2139 OIC_LOG_V(ERROR, TAG, "%s: unexpected NULL found in the oxmType array",
2144 if (0 != strcmp(doxm1->oxmType[i], doxm2->oxmType[i]))
2146 OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%s, %s)",
2147 __func__, doxm1->oxmType[i], doxm2->oxmType[i]);
2152 //Compare the contents of the oxm array and its length oxmLen.
2153 arrayLength = doxm1->oxmLen;
2155 if (arrayLength != doxm2->oxmLen)
2157 OIC_LOG_V(ERROR, TAG, "%s: oxmLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
2158 __func__, arrayLength, doxm2->oxmLen);
2162 for (size_t i = 0; i < arrayLength; i++)
2164 if (doxm1->oxm[i] != doxm2->oxm[i])
2166 OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%u, %u)",
2167 __func__, (uint32_t)doxm1->oxm[i], (uint32_t)doxm2->oxm[i]);
2172 //Compare the remaining property values.
2173 if (doxm1->oxmSel != doxm2->oxmSel)
2175 OIC_LOG_V(ERROR, TAG, "%s: oxmSel mismatch: (%u, %u)",
2176 __func__, (uint32_t)doxm1->oxmSel, (uint32_t)doxm2->oxmSel);
2180 if (doxm1->sct != doxm2->sct)
2182 OIC_LOG_V(ERROR, TAG, "%s: sct mismatch: (%u, %u)",
2183 __func__, (uint32_t)doxm1->sct, (uint32_t)doxm2->sct);
2187 if (doxm1->owned != doxm2->owned)
2189 OIC_LOG_V(ERROR, TAG, "%s: owned mismatch: (%u, %u)",
2190 __func__, (uint32_t)doxm1->owned, (uint32_t)doxm2->owned);
2194 if (0 != memcmp(&doxm1->deviceID, &doxm2->deviceID, sizeof(doxm1->deviceID)))
2196 OIC_LOG_V(ERROR, TAG, "%s: deviceID mismatch", __func__);
2200 if (doxm1->dpc != doxm2->dpc)
2202 OIC_LOG_V(ERROR, TAG, "%s: dpc mismatch: (%u, %u)",
2203 __func__, (uint32_t)doxm1->dpc, (uint32_t)doxm2->dpc);
2207 if (0 != memcmp(&doxm1->owner, &doxm2->owner, sizeof(doxm1->owner)))
2209 OIC_LOG_V(ERROR, TAG, "%s: owner mismatch", __func__);
2213 if (0 != memcmp(&doxm1->rownerID, &doxm2->rownerID, sizeof(doxm1->rownerID)))
2215 OIC_LOG_V(ERROR, TAG, "%s: rownerID mismatch", __func__);
2219 #ifdef MULTIPLE_OWNER
2220 return AreDoxmBinMOTPropertyValuesEqual(doxm1, doxm2);