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"
33 #include "oic_malloc.h"
34 #include "payload_logging.h"
37 #include "ocpayload.h"
38 #include "ocpayloadcbor.h"
39 #include "cainterface.h"
40 #include "ocserverrequest.h"
41 #include "resourcemanager.h"
42 #include "doxmresource.h"
43 #include "pstatresource.h"
44 #include "aclresource.h"
45 #include "amaclresource.h"
46 #include "pconfresource.h"
47 #include "dpairingresource.h"
48 #include "psinterface.h"
49 #include "srmresourcestrings.h"
50 #include "securevirtualresourcetypes.h"
51 #include "credresource.h"
52 #include "srmutility.h"
53 #include "pinoxmcommon.h"
54 #include "oxmverifycommon.h"
56 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
57 #include "mbedtls/md.h"
58 #include "pkix_interface.h"
61 #define TAG "OIC_SRM_DOXM"
62 #define CHAR_ZERO ('0')
64 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
65 * The value of payload size is increased until reaching belox max cbor size. */
66 static const uint16_t CBOR_SIZE = 512;
68 /** Max cbor size payload. */
69 static const uint16_t CBOR_MAX_SIZE = 4400;
71 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
72 /** MAX uuid seed size */
73 #define MAX_UUID_SEED_SIZE (64)
74 /** MIN uuid seed size */
75 #define MIN_UUID_SEED_SIZE (8)
77 /** Buffer to save the seed of device UUID */
78 static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
79 static size_t gUuidSeedSize = 0;
82 static OicSecDoxm_t *gDoxm = NULL;
83 static OCResourceHandle gDoxmHandle = NULL;
85 static OicSecOxm_t gDoxmDefaultOxm = OIC_RANDOM_DEVICE_PIN;
86 static OicSecDoxm_t gDefaultDoxm =
88 NULL, /* OicUrn_t *oxmType */
89 0, /* size_t oxmTypeLen */
90 &gDoxmDefaultOxm, /* uint16_t *oxm */
91 1, /* size_t oxmLen */
92 OIC_RANDOM_DEVICE_PIN, /* uint16_t oxmSel */
93 SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
94 false, /* bool owned */
95 {.id = {0}}, /* OicUuid_t deviceID */
97 {.id = {0}}, /* OicUuid_t owner */
99 NULL, /* OicSecSubOwner_t sub-owner list */
100 NULL, /* OicSecMomType_t multiple owner mode */
101 #endif //MULTIPLE_OWNER
102 {.id = {0}}, /* OicUuid_t rownerID */
106 * This method is internal method.
107 * the param roParsed is optionally used to know whether cborPayload has
108 * at least read only property value or not.
110 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
111 OicSecDoxm_t **doxm, bool *roParsed);
113 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
118 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
120 OICFree(doxm->oxmType[i]);
122 OICFree(doxm->oxmType);
127 #ifdef MULTIPLE_OWNER
131 //clean sub-owner list
132 if(NULL != doxm->subOwners)
134 OicSecSubOwner_t* subowner = NULL;
135 OicSecSubOwner_t* temp = NULL;
136 LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
138 LL_DELETE(doxm->subOwners, subowner);
142 #endif //MULTIPLE_OWNER
149 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
152 if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
154 return OC_STACK_INVALID_PARAM;
156 size_t cborLen = *size;
164 OCStackResult ret = OC_STACK_ERROR;
168 char* strUuid = NULL;
170 int64_t cborEncoderResult = CborNoError;
172 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
173 VERIFY_NOT_NULL(TAG, outPayload, ERROR);
174 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
176 cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
177 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
179 //OxmType -- Not Mandatory
180 if (doxm->oxmTypeLen > 0)
183 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
184 strlen(OIC_JSON_OXM_TYPE_NAME));
185 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
186 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
187 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
189 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
191 cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
192 strlen(doxm->oxmType[i]));
193 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
195 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
196 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
199 //Oxm -- Not Mandatory
200 if (doxm->oxmLen > 0 && false == rwOnly)
203 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
204 strlen(OIC_JSON_OXMS_NAME));
205 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
206 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
207 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
209 for (size_t i = 0; i < doxm->oxmLen; i++)
211 cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
212 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
214 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
215 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
218 //OxmSel -- Mandatory
219 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
220 strlen(OIC_JSON_OXM_SEL_NAME));
221 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
222 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
223 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
228 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
229 strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
230 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
231 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
232 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
236 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
237 strlen(OIC_JSON_OWNED_NAME));
238 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
239 cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
240 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
244 //DeviceId -- Mandatory
245 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
246 strlen(OIC_JSON_DEVICE_ID_NAME));
247 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
248 ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
249 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
250 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
251 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
256 #ifdef MULTIPLE_OWNER
257 //Device SubOwnerID -- Not Mandatory
260 size_t subOwnerLen = 0;
261 OicSecSubOwner_t* subOwner = NULL;
262 LL_FOREACH(doxm->subOwners, subOwner)
267 CborEncoder subOwners;
268 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
269 strlen(OIC_JSON_SUBOWNERID_NAME));
270 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
271 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
272 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
275 LL_FOREACH(doxm->subOwners, subOwner)
277 char* strUuid = NULL;
278 ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
279 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
280 cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
282 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
284 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
285 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
288 //Multiple Owner Mode -- Not Mandatory
291 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
292 strlen(OIC_JSON_MOM_NAME));
293 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
294 cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
295 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
297 #endif //MULTIPLE_OWNER
299 //devownerid -- Mandatory
300 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
301 strlen(OIC_JSON_DEVOWNERID_NAME));
302 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
303 ret = ConvertUuidToStr(&doxm->owner, &strUuid);
304 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
305 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
306 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
310 //ROwner -- Mandatory
311 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
312 strlen(OIC_JSON_ROWNERID_NAME));
313 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
314 ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
315 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
316 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
317 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
323 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
324 strlen(OIC_JSON_RT_NAME));
325 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
326 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
327 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
328 for (size_t i = 0; i < 1; i++)
330 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
331 strlen(OIC_RSRC_TYPE_SEC_DOXM));
332 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
334 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
335 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
339 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
340 strlen(OIC_JSON_IF_NAME));
341 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
342 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
343 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
344 for (size_t i = 0; i < 1; i++)
346 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
347 strlen(OC_RSRVD_INTERFACE_DEFAULT));
348 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
350 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
351 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
353 cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
354 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
356 if (CborNoError == cborEncoderResult)
358 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
359 *payload = outPayload;
363 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
365 OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
366 // reallocate and try again!
368 // Since the allocated initial memory failed, double the memory.
369 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
370 OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
371 cborEncoderResult = CborNoError;
372 ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
376 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
382 ret = OC_STACK_ERROR;
388 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
389 OicSecDoxm_t **secDoxm)
391 return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
394 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
395 OicSecDoxm_t **secDoxm, bool *roParsed)
397 if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
399 return OC_STACK_INVALID_PARAM;
402 OCStackResult ret = OC_STACK_ERROR;
406 CborError cborFindResult = CborNoError;
407 char* strUuid = NULL;
411 cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
413 OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
414 VERIFY_NOT_NULL(TAG, doxm, ERROR);
416 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
417 //OxmType -- not Mandatory
418 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
422 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
423 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
424 VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
426 doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
427 VERIFY_NOT_NULL(TAG, doxm->oxmType, ERROR);
429 cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
430 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
434 while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
436 cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
438 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
439 cborFindResult = cbor_value_advance(&oxmType);
440 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
444 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
445 //Oxm -- not Mandatory
446 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
449 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
450 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
451 VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
453 doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
454 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
456 cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
457 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
460 while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
464 cborFindResult = cbor_value_get_int(&oxm, &tmp);
465 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
466 doxm->oxm[i++] = (OicSecOxm_t)tmp;
467 cborFindResult = cbor_value_advance(&oxm);
468 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
478 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
479 doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
480 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
481 doxm->oxmLen = gDoxm->oxmLen;
482 for (size_t i = 0; i < gDoxm->oxmLen; i++)
484 doxm->oxm[i] = gDoxm->oxm[i];
488 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
489 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
493 cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
494 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
495 doxm->oxmSel = (OicSecOxm_t)oxmSel;
497 else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
499 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
500 doxm->oxmSel = gDoxm->oxmSel;
503 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
504 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
508 cborFindResult = cbor_value_get_int(&doxmMap, &sct);
509 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
510 doxm->sct = (OicSecCredType_t)sct;
517 else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
519 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
520 doxm->sct = gDoxm->sct;
523 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
524 if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
526 cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
527 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
529 else // PUT/POST JSON may not have owned so set it to the gDomx->owned
531 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
532 doxm->owned = gDoxm->owned;
535 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
536 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
538 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
539 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
540 ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
541 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
547 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
548 memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
551 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
552 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
554 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
555 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
556 ret = ConvertStrToUuid(strUuid , &doxm->owner);
557 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
563 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
564 memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
567 #ifdef MULTIPLE_OWNER
568 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
569 if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
572 cborFindResult = cbor_value_get_int(&doxmMap, &mode);
573 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
574 if(NULL == doxm->mom)
576 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
577 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
579 doxm->mom->mode = (OicSecMomType_t)mode;
581 else if(NULL != gDoxm && NULL != gDoxm->mom)
583 // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
584 if(NULL == doxm->mom)
586 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
587 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
589 doxm->mom->mode = gDoxm->mom->mode;
592 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
593 if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
595 size_t subOwnerLen = 0;
596 CborValue subOwnerCbor;
597 cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
598 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
599 VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
601 cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
602 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
604 while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
606 OCStackResult convertRes = OC_STACK_ERROR;
607 OicSecSubOwner_t* subOwner = NULL;
608 char* strUuid = NULL;
611 cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
612 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
614 subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
615 VERIFY_NOT_NULL(TAG, subOwner, ERROR);
617 convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
618 VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
619 subOwner->status = MOT_STATUS_DONE;
620 LL_APPEND(doxm->subOwners, subOwner);
622 cborFindResult = cbor_value_advance(&subOwnerCbor);
623 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
626 else if(NULL != gDoxm && NULL != gDoxm->subOwners)
628 // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
629 OicSecSubOwner_t* subOwnerItor = NULL;
630 LL_FOREACH(gDoxm->subOwners, subOwnerItor)
632 OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
633 VERIFY_NOT_NULL(TAG, subOwnerId, ERROR);
635 memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
636 subOwnerId->status = MOT_STATUS_DONE;
638 LL_APPEND(doxm->subOwners, subOwnerId);
641 #endif //MULTIPLE_OWNER
643 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
644 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
646 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
647 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
648 ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
649 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
655 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
656 memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
663 if (CborNoError != cborFindResult)
665 OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
666 DeleteDoxmBinData(doxm);
669 ret = OC_STACK_ERROR;
675 * @todo document this function including why code might need to call this.
676 * The current suspicion is that it's not being called as much as it should.
678 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
684 // Convert Doxm data into CBOR for update to persistent storage
685 uint8_t *payload = NULL;
687 OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
688 if (payload && (OC_STACK_OK == res)
689 && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
697 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
706 static bool ValidateQuery(const char * query)
708 // Send doxm resource data if the state of doxm resource
709 // matches with the query parameters.
710 // else send doxm resource data as NULL
711 // TODO Remove this check and rely on Policy Engine
712 // and Provisioning Mode to enforce provisioning-state
713 // access rules. Eventually, the PE and PM code will
714 // not send a request to the /doxm Entity Handler at all
715 // if it should not respond.
716 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
722 bool bOwnedQry = false; // does querystring contains 'owned' query ?
723 bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
724 bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
725 bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
726 bool bInterfaceQry = false; // does querystring contains 'if' query ?
727 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
728 #ifdef MULTIPLE_OWNER
729 bool bMotQry = false; // does querystring contains 'mom' and 'owned' query ?
730 bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
731 #endif //MULTIPLE_OWNER
733 OicParseQueryIter_t parseIter = {.attrPos = NULL};
735 ParseQueryIterInit((unsigned char*)query, &parseIter);
737 while (GetNextQuery(&parseIter))
739 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
742 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
747 else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
754 #ifdef MULTIPLE_OWNER
755 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
758 OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
759 if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
761 if(GetNextQuery(&parseIter))
763 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
765 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
775 #endif //MULTIPLE_OWNER
777 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
780 OicUuid_t subject = {.id={0}};
782 memcpy(subject.id, parseIter.valPos, parseIter.valLen);
783 if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
785 bDeviceIDMatch = true;
789 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
791 bInterfaceQry = true;
792 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
794 bInterfaceMatch = true;
796 return (bInterfaceQry ? bInterfaceMatch: true);
800 #ifdef MULTIPLE_OWNER
801 return ((bOwnedQry ? bOwnedMatch : true) &&
802 (bDeviceIDQry ? bDeviceIDMatch : true) &&
803 (bMotQry ? bMotMatch : true));
805 return ((bOwnedQry ? bOwnedMatch : true) &&
806 (bDeviceIDQry ? bDeviceIDMatch : true));
807 #endif //MULTIPLE_OWNER
810 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
812 OCEntityHandlerResult ehRet = OC_EH_OK;
814 OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
816 //Checking if Get request is a query.
817 if (ehRequest->query)
819 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
820 OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
821 if (!ValidateQuery(ehRequest->query))
828 * For GET or Valid Query request return doxm resource CBOR payload.
829 * For non-valid query return NULL json payload.
830 * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
831 * return valid doxm resource json.
833 uint8_t *payload = NULL;
836 if (ehRet == OC_EH_OK)
838 if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
840 OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
844 OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
845 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
847 // Send response payload to request originator
848 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
849 OC_EH_OK : OC_EH_ERROR;
856 static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
861 dst->oxmSel = src->oxmSel;
864 memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
867 memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
870 memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
872 //Update owned status
873 if(dst->owned != src->owned)
875 dst->owned = src->owned;
878 #ifdef MULTIPLE_OWNER
881 OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
884 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
887 dst->mom->mode = src->mom->mode;
891 #endif //MULTIPLE_OWNER
895 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
896 #ifdef MULTIPLE_OWNER
898 * Callback function to handle MOT DTLS handshake result.
899 * @param[out] object remote device information.
900 * @param[out] errorInfo CA Error information.
902 void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
903 const CAErrorInfo_t *errorInfo)
905 OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
907 if(CA_STATUS_OK == errorInfo->result)
909 const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
910 if(authenticatedSubOwnerInfo)
912 if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
913 authenticatedSubOwnerInfo->identity.id_length))
915 OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
919 OicSecSubOwner_t* subOwnerInst = NULL;
920 LL_FOREACH(gDoxm->subOwners, subOwnerInst)
922 if(0 == memcmp(subOwnerInst->uuid.id,
923 authenticatedSubOwnerInfo->identity.id,
924 authenticatedSubOwnerInfo->identity.id_length))
930 if(NULL == subOwnerInst)
932 subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
935 char* strUuid = NULL;
936 memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
937 authenticatedSubOwnerInfo->identity.id_length);
938 if(OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
940 OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
943 OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
945 LL_APPEND(gDoxm->subOwners, subOwnerInst);
946 if(!UpdatePersistentStorage(gDoxm))
948 OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
955 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
957 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
960 OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
962 #endif //MULTIPLE_OWNER
963 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
966 * Function to validate oxmsel with oxms.
968 * @param[in] supportedMethods Array of supported methods
969 * @param[in] numberOfMethods number of supported methods
970 * @param[out] selectedMethod Selected methods
971 * @return TRUE on success
973 static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
974 size_t numberOfMethods, OicSecOxm_t *selectedMethod)
976 bool isValidOxmsel = false;
978 OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
979 if (numberOfMethods == 0 || !supportedMethods)
981 OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
982 return isValidOxmsel;
985 for (size_t i = 0; i < numberOfMethods; i++)
987 if (*selectedMethod == supportedMethods[i])
989 isValidOxmsel = true;
995 OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
996 return isValidOxmsel;
999 OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
1001 return isValidOxmsel;
1004 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
1006 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
1007 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1008 OicUuid_t emptyOwner = {.id = {0} };
1009 static uint16_t previousMsgId = 0;
1010 bool isDuplicatedMsg = false;
1013 * Convert CBOR Doxm data into binary. This will also validate
1014 * the Doxm data received.
1016 OicSecDoxm_t *newDoxm = NULL;
1018 if (ehRequest->payload)
1020 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1021 size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1022 bool roParsed = false;
1023 OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
1024 if (newDoxm && OC_STACK_OK == res)
1027 * message ID is supported for CoAP over UDP only according to RFC 7252
1028 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1029 * In case of other transport adapter, duplicate message check is not required.
1031 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1032 previousMsgId == ehRequest->messageID)
1034 isDuplicatedMsg = true;
1037 // Check request on RO property
1038 if (true == roParsed)
1040 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
1041 ehRet = OC_EH_NOT_ACCEPTABLE;
1046 if (true == gDoxm->owned)
1048 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1050 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1051 ehRet = OC_EH_NOT_ACCEPTABLE;
1054 //Update gDoxm based on newDoxm
1055 updateWriteableProperty(newDoxm, gDoxm);
1057 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1058 #ifdef MULTIPLE_OWNER
1062 if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1064 CAResult_t caRes = CA_STATUS_FAILED;
1065 if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1067 caRes = CAEnableAnonECDHCipherSuite(false);
1068 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1069 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1071 caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter);
1072 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1073 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1075 //Set the device id to derive temporal PSK
1076 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1080 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1083 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1087 //if MOM is disabled, revert the DTLS handshake callback
1088 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1090 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1095 if(newDoxm->subOwners)
1097 OicSecSubOwner_t* subowner = NULL;
1098 OicSecSubOwner_t* temp = NULL;
1100 OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1102 if(gDoxm->subOwners)
1104 LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1106 LL_DELETE(gDoxm->subOwners, subowner);
1113 LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1115 LL_DELETE(newDoxm->subOwners, subowner);
1116 LL_APPEND(gDoxm->subOwners, subowner);
1119 #endif //MULTIPLE_OWNER
1120 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1122 //Update new state in persistent storage
1123 if (UpdatePersistentStorage(gDoxm) == true)
1129 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1130 ehRet = OC_EH_ERROR;
1136 if ((false == gDoxm->owned) && (false == newDoxm->owned))
1138 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1140 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1141 ehRet = OC_EH_NOT_ACCEPTABLE;
1145 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1148 * If current state of the device is un-owned, enable
1149 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1150 * tool can initiate JUST_WORKS ownership transfer process.
1152 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1154 gDoxm->oxmSel = newDoxm->oxmSel;
1155 //Update new state in persistent storage
1156 if ((UpdatePersistentStorage(gDoxm) == true))
1162 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1163 ehRet = OC_EH_ERROR;
1166 OIC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
1167 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1168 ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1169 #endif // __WITH_DTLS__ or __WITH_TLS__
1174 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1175 //Save the owner's UUID to derive owner credential
1176 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1178 // Update new state in persistent storage
1179 if (true == UpdatePersistentStorage(gDoxm))
1185 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1186 ehRet = OC_EH_ERROR;
1191 * Disable anonymous ECDH cipher in tinyDTLS since device is now
1194 CAResult_t caRes = CA_STATUS_OK;
1195 caRes = CAEnableAnonECDHCipherSuite(false);
1196 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1197 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1199 //In case of Mutual Verified Just-Works, verify mutualVerifNum
1200 if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1201 false == isDuplicatedMsg)
1203 uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1204 uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1205 OicUuid_t deviceID = {.id = {0}};
1207 //Generate mutualVerifNum
1208 OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1210 char label[LABEL_LEN] = {0};
1211 snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1212 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1214 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1215 ehRet = OC_EH_ERROR;
1220 CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1223 gDoxm->owner.id, sizeof(gDoxm->owner.id),
1224 gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1225 preMutualVerifNum, OWNER_PSK_LENGTH_128);
1226 if (CA_STATUS_OK != pskRet)
1228 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1229 ehRet = OC_EH_ERROR;
1234 memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1235 sizeof(mutualVerifNum));
1237 //Wait for user confirmation
1238 if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1240 ehRet = OC_EH_NOT_ACCEPTABLE;
1248 #endif // __WITH_DTLS__ or __WITH_TLS__
1251 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1254 * If current state of the device is un-owned, enable
1255 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1256 * tool can initiate JUST_WORKS ownership transfer process.
1258 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1260 gDoxm->oxmSel = newDoxm->oxmSel;
1261 //Update new state in persistent storage
1262 if ((UpdatePersistentStorage(gDoxm) == true))
1268 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1269 ehRet = OC_EH_ERROR;
1272 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1273 CAResult_t caRes = CA_STATUS_OK;
1275 caRes = CAEnableAnonECDHCipherSuite(false);
1276 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1277 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1279 caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256,
1280 ehRequest->devAddr.adapter);
1281 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1283 if (!isDuplicatedMsg)
1285 char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1286 if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1288 //Set the device id to derive temporal PSK
1289 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1292 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1293 * Credential should not be saved into SVR.
1294 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1296 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1297 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1302 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1303 ehRet = OC_EH_ERROR;
1306 #endif // __WITH_DTLS__ or __WITH_TLS__
1308 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1311 //Save the owner's UUID to derive owner credential
1312 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1314 //Update new state in persistent storage
1315 if (UpdatePersistentStorage(gDoxm) == true)
1321 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1322 ehRet = OC_EH_ERROR;
1325 #endif // __WITH_DTLS__ or __WITH_TLS__
1327 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1328 else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1330 //In case of Confirm Manufacturer Cert, get user confirmation
1331 if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1332 false == isDuplicatedMsg &&
1333 memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1335 if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1337 ehRet = OC_EH_NOT_ACCEPTABLE;
1346 //Save the owner's UUID to derive owner credential
1347 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1348 gDoxm->oxmSel = newDoxm->oxmSel;
1349 //Update new state in persistent storage
1350 if (UpdatePersistentStorage(gDoxm))
1356 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1357 ehRet = OC_EH_ERROR;
1359 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1360 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1361 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1363 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1364 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1366 #endif // __WITH_DTLS__ or __WITH_TLS__
1370 * When current state of the device is un-owned and Provisioning
1371 * Tool is attempting to change the state to 'Owned' with a
1372 * qualified value for the field 'Owner'
1374 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1375 (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1377 //Change the SVR's resource owner as owner device.
1378 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1379 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1381 ehRet = OC_EH_ERROR;
1384 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1385 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1387 ehRet = OC_EH_ERROR;
1390 ownerRes = SetCredRownerId(&gDoxm->owner);
1391 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1393 ehRet = OC_EH_ERROR;
1396 ownerRes = SetPstatRownerId(&gDoxm->owner);
1397 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1399 ehRet = OC_EH_ERROR;
1402 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1403 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1405 ehRet = OC_EH_ERROR;
1408 ownerRes = SetPconfRownerId(&gDoxm->owner);
1409 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1411 ehRet = OC_EH_ERROR;
1415 gDoxm->owned = true;
1416 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1418 // Update new state in persistent storage
1419 if (UpdatePersistentStorage(gDoxm))
1421 //Update default ACE of security resource to prevent anonymous user access.
1422 if(OC_STACK_OK == UpdateDefaultSecProvACE())
1428 OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1429 ehRet = OC_EH_ERROR;
1434 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1435 ehRet = OC_EH_ERROR;
1437 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1438 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1439 OIC_CON_MFG_CERT== gDoxm->oxmSel)
1441 CAregisterPkixInfoHandler(GetPkixInfo);
1442 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1444 #endif // __WITH_DTLS__ or __WITH_TLS__
1450 if(OC_EH_OK != ehRet)
1454 * If some error is occured while ownership transfer,
1455 * ownership transfer related resource should be revert back to initial status.
1461 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1463 if (!isDuplicatedMsg)
1465 RestoreDoxmToInitState();
1466 RestorePstatToInitState();
1467 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1473 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1478 previousMsgId = ehRequest->messageID;
1481 //Send payload to request originator
1482 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1483 OC_EH_OK : OC_EH_ERROR;
1485 DeleteDoxmBinData(newDoxm);
1490 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1491 OCEntityHandlerRequest * ehRequest,
1492 void* callbackParam)
1494 (void)callbackParam;
1495 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1497 if(NULL == ehRequest)
1502 if (flag & OC_REQUEST_FLAG)
1504 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1506 switch (ehRequest->method)
1509 ehRet = HandleDoxmGetRequest(ehRequest);
1513 ehRet = HandleDoxmPostRequest(ehRequest);
1517 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1518 OC_EH_OK : OC_EH_ERROR;
1526 OCStackResult CreateDoxmResource()
1528 OCStackResult ret = OCCreateResource(&gDoxmHandle,
1529 OIC_RSRC_TYPE_SEC_DOXM,
1530 OC_RSRVD_INTERFACE_DEFAULT,
1537 if (OC_STACK_OK != ret)
1539 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1540 DeInitDoxmResource();
1546 * Checks if DeviceID is generated during provisioning for the new device.
1547 * If DeviceID is NULL then generates the new DeviceID.
1548 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1550 static OCStackResult CheckDeviceID()
1552 OCStackResult ret = OC_STACK_ERROR;
1553 bool validId = false;
1555 for (uint8_t i = 0; i < UUID_LENGTH; i++)
1557 if (gDoxm->deviceID.id[i] != 0)
1566 char* strUuid = NULL;
1567 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1568 //If seed value is exists, generate UUID using seed with SHA256
1569 if (0 != gUuidSeedSize)
1571 uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1574 OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1575 OIC_LOG(DEBUG, TAG, "Seed value : ");
1576 OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1578 mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1579 gUuidSeed, gUuidSeedSize, hashVal);
1582 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1587 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1588 ret = OC_STACK_ERROR;
1593 if (!OCGenerateUuid(gDoxm->deviceID.id))
1595 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1596 ret = OC_STACK_ERROR;
1604 if (!OCGenerateUuid(gDoxm->deviceID.id))
1606 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1607 ret = OC_STACK_ERROR;
1615 if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1617 OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1622 OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1626 if (!UpdatePersistentStorage(gDoxm))
1628 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1629 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1641 * Get the default value.
1643 * @return the default value of doxm, @ref OicSecDoxm_t.
1645 static OicSecDoxm_t* GetDoxmDefault()
1647 OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1648 return &gDefaultDoxm;
1651 const OicSecDoxm_t* GetDoxmResourceData()
1656 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1658 * Internal API to prepare MOT
1660 static void PrepareMOT(const OicSecDoxm_t* doxm)
1662 OIC_LOG(INFO, TAG, "IN PrepareMOT");
1663 VERIFY_NOT_NULL(TAG, doxm, ERROR);
1665 if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1667 CAResult_t caRes = CA_STATUS_FAILED;
1669 OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1671 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1673 caRes = CAEnableAnonECDHCipherSuite(false);
1674 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1675 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1677 caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
1678 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1680 caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_TCP);
1681 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1683 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1685 //Set the device id to derive temporal PSK
1686 SetUuidForPinBasedOxm(&doxm->deviceID);
1690 OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1694 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1697 OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1700 OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1702 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1704 OCStackResult InitDoxmResource()
1706 OCStackResult ret = OC_STACK_ERROR;
1708 //Read DOXM resource from PS
1709 uint8_t *data = NULL;
1711 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1712 // If database read failed
1713 if (OC_STACK_OK != ret)
1715 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1719 // Read DOXM resource from PS
1720 ret = CBORPayloadToDoxm(data, size, &gDoxm);
1723 * If SVR database in persistent storage got corrupted or
1724 * is not available for some reason, a default doxm is created
1725 * which allows user to initiate doxm provisioning again.
1727 if ((OC_STACK_OK != ret) || !data || !gDoxm)
1729 gDoxm = GetDoxmDefault();
1732 //In case of the server is shut down unintentionally, we should initialize the owner
1733 if(false == gDoxm->owned)
1735 OicUuid_t emptyUuid = {.id={0}};
1736 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1739 ret = CheckDeviceID();
1740 if (ret == OC_STACK_OK)
1742 OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1743 //Instantiate 'oic.sec.doxm'
1744 ret = CreateDoxmResource();
1748 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1752 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1753 //if MOT is enabled, MOT should be prepared.
1754 if(gDoxm && gDoxm->owned)
1758 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1763 OCStackResult DeInitDoxmResource()
1765 OCStackResult ret = OCDeleteResource(gDoxmHandle);
1766 if (gDoxm != &gDefaultDoxm)
1768 DeleteDoxmBinData(gDoxm);
1772 if (OC_STACK_OK == ret)
1778 return OC_STACK_ERROR;
1782 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1784 if (deviceID && gDoxm)
1786 *deviceID = gDoxm->deviceID;
1789 return OC_STACK_ERROR;
1792 OCStackResult GetDoxmIsOwned(bool *isOwned)
1794 if (isOwned && gDoxm)
1796 *isOwned = gDoxm->owned;
1799 return OC_STACK_ERROR;
1802 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1803 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
1805 OIC_LOG_V(INFO, TAG, "In %s", __func__);
1809 return OC_STACK_INVALID_PARAM;
1811 if (MAX_UUID_SEED_SIZE < seedSize)
1813 OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
1814 return OC_STACK_INVALID_PARAM;
1816 if (MIN_UUID_SEED_SIZE > seedSize)
1818 OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
1819 return OC_STACK_INVALID_PARAM;
1822 memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
1823 memcpy(gUuidSeed, seed, seedSize);
1824 gUuidSeedSize = seedSize;
1826 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1832 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1836 if(NULL == deviceID)
1838 return OC_STACK_INVALID_PARAM;
1842 OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1843 return OC_STACK_NO_RESOURCE;
1846 //Check the device's OTM state
1848 #ifdef __WITH_DTLS__
1849 //for normal device.
1850 if(true == gDoxm->owned &&
1851 memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
1853 OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1854 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1855 return OC_STACK_ERROR;
1857 #endif //__WITH_DTLS
1859 //Save the previous UUID
1861 memcpy(tempUuid.id, gDoxm->deviceID.id, sizeof(tempUuid.id));
1864 memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1867 memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1868 memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1872 if(!UpdatePersistentStorage(gDoxm))
1874 //revert UUID in case of update error
1875 memcpy(gDoxm->deviceID.id, tempUuid.id, sizeof(tempUuid.id));
1878 memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
1879 memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
1882 OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
1883 return OC_STACK_ERROR;
1888 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
1890 OCStackResult retVal = OC_STACK_ERROR;
1893 OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned = %d.", \
1897 *devownerid = gDoxm->owner;
1898 retVal = OC_STACK_OK;
1904 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
1906 OCStackResult retVal = OC_STACK_ERROR;
1911 *rowneruuid = gDoxm->rownerID;
1912 retVal = OC_STACK_OK;
1918 #ifdef MULTIPLE_OWNER
1920 * Compare the UUID to SubOwner.
1922 * @param[in] uuid device UUID
1924 * @return true if context->subjectId exist subowner list, else false.
1926 bool IsSubOwner(const OicUuid_t* uuid)
1928 bool retVal = false;
1935 if (gDoxm && gDoxm->subOwners)
1937 if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
1942 OicSecSubOwner_t* subOwner = NULL;
1943 LL_FOREACH(gDoxm->subOwners, subOwner)
1945 if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
1953 #endif //MULTIPLE_OWNER
1956 * Function to restore doxm resurce to initial status.
1957 * This function will use in case of error while ownership transfer
1959 void RestoreDoxmToInitState()
1963 OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
1965 OicUuid_t emptyUuid = {.id={0}};
1966 memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
1967 gDoxm->owned = false;
1968 gDoxm->oxmSel = OIC_JUST_WORKS;
1970 if(!UpdatePersistentStorage(gDoxm))
1972 OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
1977 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
1979 OCStackResult ret = OC_STACK_ERROR;
1980 uint8_t *cborPayload = NULL;
1985 ret = OC_STACK_NO_RESOURCE;
1989 if( newROwner && (false == gDoxm->owned) )
1991 gDoxm->owned = true;
1992 memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
1993 memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
1995 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
1996 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1998 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
1999 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2001 OICFree(cborPayload);
2007 OICFree(cborPayload);
2011 #ifdef MULTIPLE_OWNER
2012 /** This function checks if two sets of /oic/sec/doxm MOT-specific properties are identical.
2014 * @param doxm1 is a pointer to the first @ref OicSecDoxm_t data.
2015 * @param doxm2 is a pointer to the second @ref OicSecDoxm_t data.
2017 * @return true if all of the properties are identical, else false.
2019 static bool AreDoxmBinMOTPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2021 //Compare the subOwners lists.
2022 OicSecSubOwner_t* subOwner1 = doxm1->subOwners;
2023 OicSecSubOwner_t* subOwner2 = doxm2->subOwners;
2027 if ((NULL == subOwner1) && (NULL == subOwner2))
2029 //Reached the end of both lists, so the two lists were identical.
2033 if ((NULL != subOwner1) && (NULL != subOwner2))
2035 if (0 != memcmp(&subOwner1->uuid, &subOwner2->uuid, sizeof(subOwner1->uuid)))
2037 OIC_LOG_V(ERROR, TAG, "%s: subOwner uuid mismatch", __func__);
2041 if (subOwner1->status != subOwner2->status)
2043 OIC_LOG_V(ERROR, TAG, "%s: subOwner status mismatch: (%u, %u)",
2044 __func__, (uint32_t)subOwner1->status, (uint32_t)subOwner2->status);
2048 //Go to the next elements from the two lists.
2049 subOwner1 = subOwner1->next;
2050 subOwner2 = subOwner2->next;
2054 OIC_LOG_V(ERROR, TAG, "%s: subOwner list length mismatch", __func__);
2058 // Compare the mom values.
2059 if (NULL == doxm1->mom)
2061 if (NULL != doxm2->mom)
2063 OIC_LOG_V(ERROR, TAG, "%s: doxm1->mom is NULL", __func__);
2070 if (NULL == doxm2->mom)
2072 OIC_LOG_V(ERROR, TAG, "%s: doxm2->mom is NULL", __func__);
2076 if (doxm1->mom->mode != doxm2->mom->mode)
2078 OIC_LOG_V(ERROR, TAG, "%s: mom->mode mismatch: (%u, %u)",
2079 __func__, (uint32_t)doxm1->mom->mode, (uint32_t)doxm2->mom->mode);
2085 #endif //#ifdef MULTIPLE_OWNER
2087 bool AreDoxmBinPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2089 if (NULL == doxm1 || NULL == doxm2)
2091 OIC_LOG_V(ERROR, TAG, "%s: unxpected NULL doxm pointer", __func__);
2095 //Compare the contents of the oxmType array and its length oxmTypeLen.
2096 size_t arrayLength = doxm1->oxmTypeLen;
2098 if (arrayLength != doxm2->oxmTypeLen)
2100 OIC_LOG_V(ERROR, TAG, "%s: oxmTypeLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
2101 __func__, arrayLength, doxm2->oxmTypeLen);
2105 for (size_t i = 0; i < arrayLength; i++)
2107 if (NULL == doxm1->oxmType[i] || NULL == doxm2->oxmType[i])
2109 OIC_LOG_V(ERROR, TAG, "%s: unexpected NULL found in the oxmType array",
2114 if (0 != strcmp(doxm1->oxmType[i], doxm2->oxmType[i]))
2116 OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%s, %s)",
2117 __func__, doxm1->oxmType[i], doxm2->oxmType[i]);
2122 //Compare the contents of the oxm array and its length oxmLen.
2123 arrayLength = doxm1->oxmLen;
2125 if (arrayLength != doxm2->oxmLen)
2127 OIC_LOG_V(ERROR, TAG, "%s: oxmLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
2128 __func__, arrayLength, doxm2->oxmLen);
2132 for (size_t i = 0; i < arrayLength; i++)
2134 if (doxm1->oxm[i] != doxm2->oxm[i])
2136 OIC_LOG_V(ERROR, TAG, "%s: oxmType mismatch: (%u, %u)",
2137 __func__, (uint32_t)doxm1->oxm[i], (uint32_t)doxm2->oxm[i]);
2142 //Compare the remaining property values.
2143 if (doxm1->oxmSel != doxm2->oxmSel)
2145 OIC_LOG_V(ERROR, TAG, "%s: oxmSel mismatch: (%u, %u)",
2146 __func__, (uint32_t)doxm1->oxmSel, (uint32_t)doxm2->oxmSel);
2150 if (doxm1->sct != doxm2->sct)
2152 OIC_LOG_V(ERROR, TAG, "%s: sct mismatch: (%u, %u)",
2153 __func__, (uint32_t)doxm1->sct, (uint32_t)doxm2->sct);
2157 if (doxm1->owned != doxm2->owned)
2159 OIC_LOG_V(ERROR, TAG, "%s: owned mismatch: (%u, %u)",
2160 __func__, (uint32_t)doxm1->owned, (uint32_t)doxm2->owned);
2164 if (0 != memcmp(&doxm1->deviceID, &doxm2->deviceID, sizeof(doxm1->deviceID)))
2166 OIC_LOG_V(ERROR, TAG, "%s: deviceID mismatch", __func__);
2170 if (doxm1->dpc != doxm2->dpc)
2172 OIC_LOG_V(ERROR, TAG, "%s: dpc mismatch: (%u, %u)",
2173 __func__, (uint32_t)doxm1->dpc, (uint32_t)doxm2->dpc);
2177 if (0 != memcmp(&doxm1->owner, &doxm2->owner, sizeof(doxm1->owner)))
2179 OIC_LOG_V(ERROR, TAG, "%s: owner mismatch", __func__);
2183 if (0 != memcmp(&doxm1->rownerID, &doxm2->rownerID, sizeof(doxm1->rownerID)))
2185 OIC_LOG_V(ERROR, TAG, "%s: rownerID mismatch", __func__);
2189 #ifdef MULTIPLE_OWNER
2190 return AreDoxmBinMOTPropertyValuesEqual(doxm1, doxm2);