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"
34 #include "oic_malloc.h"
35 #include "payload_logging.h"
38 #include "ocpayload.h"
39 #include "ocpayloadcbor.h"
40 #include "cainterface.h"
41 #include "ocserverrequest.h"
42 #include "resourcemanager.h"
43 #include "doxmresource.h"
44 #include "pstatresource.h"
45 #include "aclresource.h"
46 #include "amaclresource.h"
47 #include "pconfresource.h"
48 #include "dpairingresource.h"
49 #include "psinterface.h"
50 #include "srmresourcestrings.h"
51 #include "securevirtualresourcetypes.h"
52 #include "credresource.h"
53 #include "srmutility.h"
54 #include "pinoxmcommon.h"
55 #include "oxmverifycommon.h"
57 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
58 #include "mbedtls/md.h"
59 #include "pkix_interface.h"
62 #define TAG "OIC_SRM_DOXM"
63 #define CHAR_ZERO ('0')
65 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
66 * The value of payload size is increased until reaching belox max cbor size. */
67 static const uint16_t CBOR_SIZE = 512;
69 /** Max cbor size payload. */
70 static const uint16_t CBOR_MAX_SIZE = 4400;
72 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
73 /** MAX uuid seed size */
74 #define MAX_UUID_SEED_SIZE (64)
75 /** MIN uuid seed size */
76 #define MIN_UUID_SEED_SIZE (8)
78 /** Buffer to save the seed of device UUID */
79 static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
80 static size_t gUuidSeedSize = 0;
83 static OicSecDoxm_t *gDoxm = NULL;
84 static OCResourceHandle gDoxmHandle = NULL;
86 static OicSecOxm_t gDoxmDefaultOxm = OIC_RANDOM_DEVICE_PIN;
87 static OicSecDoxm_t gDefaultDoxm =
89 NULL, /* OicUrn_t *oxmType */
90 0, /* size_t oxmTypeLen */
91 &gDoxmDefaultOxm, /* uint16_t *oxm */
92 1, /* size_t oxmLen */
93 OIC_RANDOM_DEVICE_PIN, /* uint16_t oxmSel */
94 SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
95 false, /* bool owned */
96 {.id = {0}}, /* OicUuid_t deviceID */
98 {.id = {0}}, /* OicUuid_t owner */
100 NULL, /* OicSecSubOwner_t sub-owner list */
101 NULL, /* OicSecMomType_t multiple owner mode */
102 #endif //MULTIPLE_OWNER
103 {.id = {0}}, /* OicUuid_t rownerID */
107 * This method is internal method.
108 * the param roParsed is optionally used to know whether cborPayload has
109 * at least read only property value or not.
111 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
112 OicSecDoxm_t **doxm, bool *roParsed);
114 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
119 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
121 OICFree(doxm->oxmType[i]);
123 OICFree(doxm->oxmType);
128 #ifdef MULTIPLE_OWNER
132 //clean sub-owner list
133 if(NULL != doxm->subOwners)
135 OicSecSubOwner_t* subowner = NULL;
136 OicSecSubOwner_t* temp = NULL;
137 LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
139 LL_DELETE(doxm->subOwners, subowner);
143 #endif //MULTIPLE_OWNER
150 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
153 if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
155 return OC_STACK_INVALID_PARAM;
157 size_t cborLen = *size;
165 OCStackResult ret = OC_STACK_ERROR;
169 char* strUuid = NULL;
171 int64_t cborEncoderResult = CborNoError;
173 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
174 VERIFY_NOT_NULL(TAG, outPayload, ERROR);
175 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
177 cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
178 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
180 //OxmType -- Not Mandatory
181 if (doxm->oxmTypeLen > 0)
184 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
185 strlen(OIC_JSON_OXM_TYPE_NAME));
186 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
187 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
188 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
190 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
192 cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
193 strlen(doxm->oxmType[i]));
194 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
196 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
197 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
200 //Oxm -- Not Mandatory
201 if (doxm->oxmLen > 0 && false == rwOnly)
204 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
205 strlen(OIC_JSON_OXMS_NAME));
206 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
207 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
208 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
210 for (size_t i = 0; i < doxm->oxmLen; i++)
212 cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
213 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
215 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
216 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
219 //OxmSel -- Mandatory
220 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
221 strlen(OIC_JSON_OXM_SEL_NAME));
222 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
223 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
224 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
229 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
230 strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
231 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
232 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
233 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
237 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
238 strlen(OIC_JSON_OWNED_NAME));
239 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
240 cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
241 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
245 //DeviceId -- Mandatory
246 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
247 strlen(OIC_JSON_DEVICE_ID_NAME));
248 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
249 ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
250 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
251 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
252 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
257 #ifdef MULTIPLE_OWNER
258 //Device SubOwnerID -- Not Mandatory
261 size_t subOwnerLen = 0;
262 OicSecSubOwner_t* subOwner = NULL;
263 LL_FOREACH(doxm->subOwners, subOwner)
268 CborEncoder subOwners;
269 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
270 strlen(OIC_JSON_SUBOWNERID_NAME));
271 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
272 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
273 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
276 LL_FOREACH(doxm->subOwners, subOwner)
278 char* strUuid = NULL;
279 ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
280 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
281 cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
283 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
285 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
286 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
289 //Multiple Owner Mode -- Not Mandatory
292 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
293 strlen(OIC_JSON_MOM_NAME));
294 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
295 cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
296 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
298 #endif //MULTIPLE_OWNER
300 //devownerid -- Mandatory
301 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
302 strlen(OIC_JSON_DEVOWNERID_NAME));
303 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
304 ret = ConvertUuidToStr(&doxm->owner, &strUuid);
305 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
306 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
307 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
311 //ROwner -- Mandatory
312 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
313 strlen(OIC_JSON_ROWNERID_NAME));
314 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
315 ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
316 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
317 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
318 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
324 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
325 strlen(OIC_JSON_RT_NAME));
326 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
327 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
328 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
329 for (size_t i = 0; i < 1; i++)
331 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
332 strlen(OIC_RSRC_TYPE_SEC_DOXM));
333 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
335 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
336 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
340 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
341 strlen(OIC_JSON_IF_NAME));
342 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
343 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
344 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
345 for (size_t i = 0; i < 1; i++)
347 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
348 strlen(OC_RSRVD_INTERFACE_DEFAULT));
349 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
351 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
352 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
354 cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
355 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
357 if (CborNoError == cborEncoderResult)
359 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
360 *payload = outPayload;
364 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
366 OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
367 // reallocate and try again!
369 // Since the allocated initial memory failed, double the memory.
370 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
371 OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
372 cborEncoderResult = CborNoError;
373 ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
377 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
383 ret = OC_STACK_ERROR;
389 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
390 OicSecDoxm_t **secDoxm)
392 return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
395 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
396 OicSecDoxm_t **secDoxm, bool *roParsed)
398 if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
400 return OC_STACK_INVALID_PARAM;
403 OCStackResult ret = OC_STACK_ERROR;
407 CborError cborFindResult = CborNoError;
408 char* strUuid = NULL;
412 cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
414 OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
415 VERIFY_NOT_NULL(TAG, doxm, ERROR);
417 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
418 //OxmType -- not Mandatory
419 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
423 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
424 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
425 VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
427 doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
428 VERIFY_NOT_NULL(TAG, doxm->oxmType, ERROR);
430 cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
431 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
435 while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
437 cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
439 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
440 cborFindResult = cbor_value_advance(&oxmType);
441 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
445 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
446 //Oxm -- not Mandatory
447 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
450 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
451 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
452 VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
454 doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
455 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
457 cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
458 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
461 while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
465 cborFindResult = cbor_value_get_int(&oxm, &tmp);
466 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
467 doxm->oxm[i++] = (OicSecOxm_t)tmp;
468 cborFindResult = cbor_value_advance(&oxm);
469 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
479 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
480 doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
481 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
482 doxm->oxmLen = gDoxm->oxmLen;
483 for (size_t i = 0; i < gDoxm->oxmLen; i++)
485 doxm->oxm[i] = gDoxm->oxm[i];
489 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
490 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
494 cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
495 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
496 doxm->oxmSel = (OicSecOxm_t)oxmSel;
498 else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
500 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
501 doxm->oxmSel = gDoxm->oxmSel;
504 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
505 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
509 cborFindResult = cbor_value_get_int(&doxmMap, &sct);
510 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
511 doxm->sct = (OicSecCredType_t)sct;
518 else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
520 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
521 doxm->sct = gDoxm->sct;
524 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
525 if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
527 cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
528 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
530 else // PUT/POST JSON may not have owned so set it to the gDomx->owned
532 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
533 doxm->owned = gDoxm->owned;
536 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
537 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
539 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
540 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
541 ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
542 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
548 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
549 memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
552 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
553 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
555 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
556 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
557 ret = ConvertStrToUuid(strUuid , &doxm->owner);
558 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
564 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
565 memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
568 #ifdef MULTIPLE_OWNER
569 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
570 if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
573 cborFindResult = cbor_value_get_int(&doxmMap, &mode);
574 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
575 if(NULL == doxm->mom)
577 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
578 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
580 doxm->mom->mode = (OicSecMomType_t)mode;
582 else if(NULL != gDoxm && NULL != gDoxm->mom)
584 // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
585 if(NULL == doxm->mom)
587 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
588 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
590 doxm->mom->mode = gDoxm->mom->mode;
593 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
594 if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
596 size_t subOwnerLen = 0;
597 CborValue subOwnerCbor;
598 cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
599 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
600 VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
602 cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
603 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
605 while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
607 OCStackResult convertRes = OC_STACK_ERROR;
608 OicSecSubOwner_t* subOwner = NULL;
609 char* strUuid = NULL;
612 cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
613 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
615 subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
616 VERIFY_NOT_NULL(TAG, subOwner, ERROR);
618 convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
619 VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
620 subOwner->status = MOT_STATUS_DONE;
621 LL_APPEND(doxm->subOwners, subOwner);
623 cborFindResult = cbor_value_advance(&subOwnerCbor);
624 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
627 else if(NULL != gDoxm && NULL != gDoxm->subOwners)
629 // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
630 OicSecSubOwner_t* subOwnerItor = NULL;
631 LL_FOREACH(gDoxm->subOwners, subOwnerItor)
633 OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
634 VERIFY_NOT_NULL(TAG, subOwnerId, ERROR);
636 memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
637 subOwnerId->status = MOT_STATUS_DONE;
639 LL_APPEND(doxm->subOwners, subOwnerId);
642 #endif //MULTIPLE_OWNER
644 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
645 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
647 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
648 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
649 ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
650 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
656 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
657 memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
664 if (CborNoError != cborFindResult)
666 OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
667 DeleteDoxmBinData(doxm);
670 ret = OC_STACK_ERROR;
676 * @todo document this function including why code might need to call this.
677 * The current suspicion is that it's not being called as much as it should.
679 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
685 // Convert Doxm data into CBOR for update to persistent storage
686 uint8_t *payload = NULL;
688 OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
689 if (payload && (OC_STACK_OK == res)
690 && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
698 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
707 static bool ValidateQuery(const char * query)
709 // Send doxm resource data if the state of doxm resource
710 // matches with the query parameters.
711 // else send doxm resource data as NULL
712 // TODO Remove this check and rely on Policy Engine
713 // and Provisioning Mode to enforce provisioning-state
714 // access rules. Eventually, the PE and PM code will
715 // not send a request to the /doxm Entity Handler at all
716 // if it should not respond.
717 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
723 bool bOwnedQry = false; // does querystring contains 'owned' query ?
724 bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
725 bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
726 bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
727 bool bInterfaceQry = false; // does querystring contains 'if' query ?
728 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
729 #ifdef MULTIPLE_OWNER
730 bool bMotQry = false; // does querystring contains 'mom' and 'owned' query ?
731 bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
732 #endif //MULTIPLE_OWNER
734 OicParseQueryIter_t parseIter = {.attrPos = NULL};
736 ParseQueryIterInit((unsigned char*)query, &parseIter);
738 while (GetNextQuery(&parseIter))
740 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
743 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
748 else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
755 #ifdef MULTIPLE_OWNER
756 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
759 OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
760 if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
762 if(GetNextQuery(&parseIter))
764 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
766 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
776 #endif //MULTIPLE_OWNER
778 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
781 OicUuid_t subject = {.id={0}};
783 memcpy(subject.id, parseIter.valPos, parseIter.valLen);
784 if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
786 bDeviceIDMatch = true;
790 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
792 bInterfaceQry = true;
793 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
795 bInterfaceMatch = true;
797 return (bInterfaceQry ? bInterfaceMatch: true);
801 #ifdef MULTIPLE_OWNER
802 return ((bOwnedQry ? bOwnedMatch : true) &&
803 (bDeviceIDQry ? bDeviceIDMatch : true) &&
804 (bMotQry ? bMotMatch : true));
806 return ((bOwnedQry ? bOwnedMatch : true) &&
807 (bDeviceIDQry ? bDeviceIDMatch : true));
808 #endif //MULTIPLE_OWNER
811 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
813 OCEntityHandlerResult ehRet = OC_EH_OK;
815 OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
817 //Checking if Get request is a query.
818 if (ehRequest->query)
820 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
821 OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
822 if (!ValidateQuery(ehRequest->query))
829 * For GET or Valid Query request return doxm resource CBOR payload.
830 * For non-valid query return NULL json payload.
831 * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
832 * return valid doxm resource json.
834 uint8_t *payload = NULL;
837 if (ehRet == OC_EH_OK)
839 if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
841 OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
845 OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
846 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
848 // Send response payload to request originator
849 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
850 OC_EH_OK : OC_EH_ERROR;
857 static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
862 dst->oxmSel = src->oxmSel;
865 memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
868 memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
871 memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
873 //Update owned status
874 if(dst->owned != src->owned)
876 dst->owned = src->owned;
879 #ifdef MULTIPLE_OWNER
882 OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
885 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
888 dst->mom->mode = src->mom->mode;
892 #endif //MULTIPLE_OWNER
896 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
897 #ifdef MULTIPLE_OWNER
899 * Callback function to handle MOT DTLS handshake result.
900 * @param[out] object remote device information.
901 * @param[out] errorInfo CA Error information.
903 void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
904 const CAErrorInfo_t *errorInfo)
906 OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
908 if(CA_STATUS_OK == errorInfo->result)
910 const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
911 if(authenticatedSubOwnerInfo)
913 if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
914 authenticatedSubOwnerInfo->identity.id_length))
916 OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
920 OicSecSubOwner_t* subOwnerInst = NULL;
921 LL_FOREACH(gDoxm->subOwners, subOwnerInst)
923 if(0 == memcmp(subOwnerInst->uuid.id,
924 authenticatedSubOwnerInfo->identity.id,
925 authenticatedSubOwnerInfo->identity.id_length))
931 if(NULL == subOwnerInst)
933 subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
936 char* strUuid = NULL;
937 memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
938 authenticatedSubOwnerInfo->identity.id_length);
939 if(OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
941 OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
944 OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
946 LL_APPEND(gDoxm->subOwners, subOwnerInst);
947 if(!UpdatePersistentStorage(gDoxm))
949 OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
956 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
958 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
961 OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
963 #endif //MULTIPLE_OWNER
964 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
967 * Function to validate oxmsel with oxms.
969 * @param[in] supportedMethods Array of supported methods
970 * @param[in] numberOfMethods number of supported methods
971 * @param[out] selectedMethod Selected methods
972 * @return TRUE on success
974 static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
975 size_t numberOfMethods, OicSecOxm_t *selectedMethod)
977 bool isValidOxmsel = false;
979 OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
980 if (numberOfMethods == 0 || !supportedMethods)
982 OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
983 return isValidOxmsel;
986 for (size_t i = 0; i < numberOfMethods; i++)
988 if (*selectedMethod == supportedMethods[i])
990 isValidOxmsel = true;
996 OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
997 return isValidOxmsel;
1000 OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
1002 return isValidOxmsel;
1005 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1006 static void DoxmDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
1008 OIC_LOG_V(DEBUG, TAG, "In %s(%p, %p)", __func__, endpoint, info);
1010 if ((NULL != endpoint) && (NULL != info) && (CA_STATUS_OK == info->result))
1013 * Allow this OBT endpoint to bypass ACE checks for SVRs, while this
1014 * device is not yet owned.
1016 OC_VERIFY(CASetSecureEndpointAttribute(endpoint,
1017 CA_SECURE_ENDPOINT_ATTRIBUTE_ADMINISTRATOR));
1020 OIC_LOG_V(DEBUG, TAG, "Out %s(%p, %p)", __func__, endpoint, info);
1023 static void RegisterOTMSslHandshakeCallback(CAErrorCallback callback)
1025 OC_VERIFY(CA_STATUS_OK == CAregisterSslHandshakeCallback(callback));
1027 #endif // __WITH_DTLS__ or __WITH_TLS__
1029 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
1031 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
1032 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1033 OicUuid_t emptyOwner = {.id = {0} };
1034 static uint16_t previousMsgId = 0;
1035 bool isDuplicatedMsg = false;
1038 * Convert CBOR Doxm data into binary. This will also validate
1039 * the Doxm data received.
1041 OicSecDoxm_t *newDoxm = NULL;
1043 if (ehRequest->payload)
1045 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1046 size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1047 bool roParsed = false;
1048 OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
1049 if (newDoxm && OC_STACK_OK == res)
1052 * message ID is supported for CoAP over UDP only according to RFC 7252
1053 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1054 * In case of other transport adapter, duplicate message check is not required.
1056 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1057 previousMsgId == ehRequest->messageID)
1059 isDuplicatedMsg = true;
1062 // Check request on RO property
1063 if (true == roParsed)
1065 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
1066 ehRet = OC_EH_NOT_ACCEPTABLE;
1071 if (true == gDoxm->owned)
1073 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1075 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1076 ehRet = OC_EH_NOT_ACCEPTABLE;
1079 //Update gDoxm based on newDoxm
1080 updateWriteableProperty(newDoxm, gDoxm);
1082 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1083 #ifdef MULTIPLE_OWNER
1087 if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1089 CAResult_t caRes = CA_STATUS_FAILED;
1090 if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1092 caRes = CAEnableAnonECDHCipherSuite(false);
1093 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1094 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1096 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1097 caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter);
1098 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1099 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1101 //Set the device id to derive temporal PSK
1102 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1106 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1109 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1113 //if MOM is disabled, revert the DTLS handshake callback
1114 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1116 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1121 if(newDoxm->subOwners)
1123 OicSecSubOwner_t* subowner = NULL;
1124 OicSecSubOwner_t* temp = NULL;
1126 OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1128 if(gDoxm->subOwners)
1130 LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1132 LL_DELETE(gDoxm->subOwners, subowner);
1139 LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1141 LL_DELETE(newDoxm->subOwners, subowner);
1142 LL_APPEND(gDoxm->subOwners, subowner);
1145 #endif //MULTIPLE_OWNER
1146 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1148 //Update new state in persistent storage
1149 if (UpdatePersistentStorage(gDoxm) == true)
1155 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1156 ehRet = OC_EH_ERROR;
1162 if ((false == gDoxm->owned) && (false == newDoxm->owned))
1164 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1166 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1167 ehRet = OC_EH_NOT_ACCEPTABLE;
1171 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1174 * If current state of the device is un-owned, enable
1175 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1176 * tool can initiate JUST_WORKS ownership transfer process.
1178 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1180 gDoxm->oxmSel = newDoxm->oxmSel;
1181 //Update new state in persistent storage
1182 if ((UpdatePersistentStorage(gDoxm) == true))
1188 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1189 ehRet = OC_EH_ERROR;
1192 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1193 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1194 OIC_LOG(INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
1195 ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1196 #endif // __WITH_DTLS__ or __WITH_TLS__
1201 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1202 //Save the owner's UUID to derive owner credential
1203 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1205 // Update new state in persistent storage
1206 if (true == UpdatePersistentStorage(gDoxm))
1212 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1213 ehRet = OC_EH_ERROR;
1218 * Disable anonymous ECDH cipher in tinyDTLS since device is now
1221 RegisterOTMSslHandshakeCallback(NULL);
1222 CAResult_t caRes = CA_STATUS_OK;
1223 caRes = CAEnableAnonECDHCipherSuite(false);
1224 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1225 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1227 //In case of Mutual Verified Just-Works, verify mutualVerifNum
1228 if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1229 false == isDuplicatedMsg)
1231 uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1232 uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1233 OicUuid_t deviceID = {.id = {0}};
1235 //Generate mutualVerifNum
1236 OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1238 char label[LABEL_LEN] = {0};
1239 snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1240 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1242 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1243 ehRet = OC_EH_ERROR;
1248 CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1251 gDoxm->owner.id, sizeof(gDoxm->owner.id),
1252 gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1253 preMutualVerifNum, OWNER_PSK_LENGTH_128);
1254 if (CA_STATUS_OK != pskRet)
1256 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1257 ehRet = OC_EH_ERROR;
1262 memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1263 sizeof(mutualVerifNum));
1265 //Wait for user confirmation
1266 if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1268 ehRet = OC_EH_NOT_ACCEPTABLE;
1276 #endif // __WITH_DTLS__ or __WITH_TLS__
1279 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1282 * If current state of the device is un-owned, enable
1283 * ECDHE_PSK cipher so that the Provisioning tool can
1284 * initiate the ownership transfer.
1286 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1288 gDoxm->oxmSel = newDoxm->oxmSel;
1289 //Update new state in persistent storage
1290 if ((UpdatePersistentStorage(gDoxm) == true))
1296 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1297 ehRet = OC_EH_ERROR;
1300 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1301 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1302 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1303 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1305 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1306 caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256,
1307 ehRequest->devAddr.adapter);
1308 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1310 if (!isDuplicatedMsg)
1312 char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1313 if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1315 //Set the device id to derive temporal PSK
1316 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1319 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1320 * Credential should not be saved into SVR.
1321 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1323 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1324 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1329 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1330 ehRet = OC_EH_ERROR;
1333 #endif // __WITH_DTLS__ or __WITH_TLS__
1335 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1338 //Save the owner's UUID to derive owner credential
1339 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1341 //Update new state in persistent storage
1342 if (UpdatePersistentStorage(gDoxm) == true)
1348 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1349 ehRet = OC_EH_ERROR;
1352 #endif // __WITH_DTLS__ or __WITH_TLS__
1354 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1355 else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1357 //In case of Confirm Manufacturer Cert, get user confirmation
1358 if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1359 false == isDuplicatedMsg &&
1360 memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1362 if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1364 ehRet = OC_EH_NOT_ACCEPTABLE;
1373 //Save the owner's UUID to derive owner credential
1374 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1375 gDoxm->oxmSel = newDoxm->oxmSel;
1376 //Update new state in persistent storage
1377 if (UpdatePersistentStorage(gDoxm))
1383 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1384 ehRet = OC_EH_ERROR;
1387 RegisterOTMSslHandshakeCallback(NULL);
1388 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1389 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1390 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1392 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1393 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1395 #endif // __WITH_DTLS__ or __WITH_TLS__
1399 * When current state of the device is un-owned and Provisioning
1400 * Tool is attempting to change the state to 'Owned' with a
1401 * qualified value for the field 'Owner'
1403 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1404 (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1406 //Change the SVR's resource owner as owner device.
1407 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1408 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1410 ehRet = OC_EH_ERROR;
1413 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1414 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1416 ehRet = OC_EH_ERROR;
1419 ownerRes = SetCredRownerId(&gDoxm->owner);
1420 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1422 ehRet = OC_EH_ERROR;
1425 ownerRes = SetPstatRownerId(&gDoxm->owner);
1426 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1428 ehRet = OC_EH_ERROR;
1431 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1432 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1434 ehRet = OC_EH_ERROR;
1437 ownerRes = SetPconfRownerId(&gDoxm->owner);
1438 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1440 ehRet = OC_EH_ERROR;
1444 gDoxm->owned = true;
1445 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1447 // Update new state in persistent storage
1448 if (UpdatePersistentStorage(gDoxm))
1450 //Update default ACE of security resource to prevent anonymous user access.
1451 if(OC_STACK_OK == UpdateDefaultSecProvACE())
1457 OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1458 ehRet = OC_EH_ERROR;
1463 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1464 ehRet = OC_EH_ERROR;
1466 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1467 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1468 OIC_CON_MFG_CERT== gDoxm->oxmSel)
1470 CAregisterPkixInfoHandler(GetPkixInfo);
1471 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1473 #endif // __WITH_DTLS__ or __WITH_TLS__
1479 if(OC_EH_OK != ehRet)
1483 * If some error is occured while ownership transfer,
1484 * ownership transfer related resource should be revert back to initial status.
1490 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1492 if (!isDuplicatedMsg)
1494 RestoreDoxmToInitState();
1495 RestorePstatToInitState();
1496 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1502 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1507 previousMsgId = ehRequest->messageID;
1510 //Send payload to request originator
1511 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1512 OC_EH_OK : OC_EH_ERROR;
1514 DeleteDoxmBinData(newDoxm);
1519 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1520 OCEntityHandlerRequest * ehRequest,
1521 void* callbackParam)
1523 (void)callbackParam;
1524 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1526 if(NULL == ehRequest)
1531 if (flag & OC_REQUEST_FLAG)
1533 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1535 switch (ehRequest->method)
1538 ehRet = HandleDoxmGetRequest(ehRequest);
1542 ehRet = HandleDoxmPostRequest(ehRequest);
1546 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1547 OC_EH_OK : OC_EH_ERROR;
1555 OCStackResult CreateDoxmResource()
1557 OCStackResult ret = OCCreateResource(&gDoxmHandle,
1558 OIC_RSRC_TYPE_SEC_DOXM,
1559 OC_RSRVD_INTERFACE_DEFAULT,
1566 if (OC_STACK_OK != ret)
1568 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1569 DeInitDoxmResource();
1575 * Checks if DeviceID is generated during provisioning for the new device.
1576 * If DeviceID is NULL then generates the new DeviceID.
1577 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1579 static OCStackResult CheckDeviceID()
1581 OCStackResult ret = OC_STACK_ERROR;
1582 bool validId = false;
1584 for (uint8_t i = 0; i < UUID_LENGTH; i++)
1586 if (gDoxm->deviceID.id[i] != 0)
1595 char* strUuid = NULL;
1596 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1597 //If seed value is exists, generate UUID using seed with SHA256
1598 if (0 != gUuidSeedSize)
1600 uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1603 OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1604 OIC_LOG(DEBUG, TAG, "Seed value : ");
1605 OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1607 mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1608 gUuidSeed, gUuidSeedSize, hashVal);
1611 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1616 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1617 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 (!OCGenerateUuid(gDoxm->deviceID.id))
1635 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1636 ret = OC_STACK_ERROR;
1644 if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1646 OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1651 OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1655 if (!UpdatePersistentStorage(gDoxm))
1657 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1658 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1670 * Get the default value.
1672 * @return the default value of doxm, @ref OicSecDoxm_t.
1674 static OicSecDoxm_t* GetDoxmDefault()
1676 OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1677 return &gDefaultDoxm;
1680 const OicSecDoxm_t* GetDoxmResourceData()
1685 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1687 * Internal API to prepare MOT
1689 static void PrepareMOT(const OicSecDoxm_t* doxm)
1691 OIC_LOG(INFO, TAG, "IN PrepareMOT");
1692 VERIFY_NOT_NULL(TAG, doxm, ERROR);
1694 if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1696 CAResult_t caRes = CA_STATUS_FAILED;
1698 OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1700 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1702 caRes = CAEnableAnonECDHCipherSuite(false);
1703 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1704 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1706 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1707 caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
1708 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1710 caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_TCP);
1711 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1713 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1715 //Set the device id to derive temporal PSK
1716 SetUuidForPinBasedOxm(&doxm->deviceID);
1720 OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1724 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1727 OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1730 OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1732 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1734 OCStackResult InitDoxmResource()
1736 OCStackResult ret = OC_STACK_ERROR;
1738 //Read DOXM resource from PS
1739 uint8_t *data = NULL;
1741 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1742 // If database read failed
1743 if (OC_STACK_OK != ret)
1745 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1749 // Read DOXM resource from PS
1750 ret = CBORPayloadToDoxm(data, size, &gDoxm);
1753 * If SVR database in persistent storage got corrupted or
1754 * is not available for some reason, a default doxm is created
1755 * which allows user to initiate doxm provisioning again.
1757 if ((OC_STACK_OK != ret) || !data || !gDoxm)
1759 gDoxm = GetDoxmDefault();
1762 //In case of the server is shut down unintentionally, we should initialize the owner
1763 if(false == gDoxm->owned)
1765 OicUuid_t emptyUuid = {.id={0}};
1766 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
1769 ret = CheckDeviceID();
1770 if (ret == OC_STACK_OK)
1772 OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
1773 //Instantiate 'oic.sec.doxm'
1774 ret = CreateDoxmResource();
1778 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
1782 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1783 //if MOT is enabled, MOT should be prepared.
1784 if(gDoxm && gDoxm->owned)
1788 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1793 OCStackResult DeInitDoxmResource()
1795 OCStackResult ret = OCDeleteResource(gDoxmHandle);
1796 if (gDoxm != &gDefaultDoxm)
1798 DeleteDoxmBinData(gDoxm);
1802 if (OC_STACK_OK == ret)
1808 return OC_STACK_ERROR;
1812 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
1814 if (deviceID && gDoxm)
1816 *deviceID = gDoxm->deviceID;
1819 return OC_STACK_ERROR;
1822 OCStackResult GetDoxmIsOwned(bool *isOwned)
1824 if (isOwned && gDoxm)
1826 *isOwned = gDoxm->owned;
1829 return OC_STACK_ERROR;
1832 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1833 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
1835 OIC_LOG_V(INFO, TAG, "In %s", __func__);
1839 return OC_STACK_INVALID_PARAM;
1841 if (MAX_UUID_SEED_SIZE < seedSize)
1843 OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
1844 return OC_STACK_INVALID_PARAM;
1846 if (MIN_UUID_SEED_SIZE > seedSize)
1848 OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
1849 return OC_STACK_INVALID_PARAM;
1852 memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
1853 memcpy(gUuidSeed, seed, seedSize);
1854 gUuidSeedSize = seedSize;
1856 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1862 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
1866 if(NULL == deviceID)
1868 return OC_STACK_INVALID_PARAM;
1872 OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
1873 return OC_STACK_NO_RESOURCE;
1876 //Check the device's OTM state
1878 #ifdef __WITH_DTLS__
1879 //for normal device.
1880 if(true == gDoxm->owned &&
1881 memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
1883 OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
1884 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
1885 return OC_STACK_ERROR;
1887 #endif //__WITH_DTLS
1889 //Save the previous UUID
1891 memcpy(tempUuid.id, gDoxm->deviceID.id, sizeof(tempUuid.id));
1894 memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
1897 memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
1898 memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
1902 if(!UpdatePersistentStorage(gDoxm))
1904 //revert UUID in case of update error
1905 memcpy(gDoxm->deviceID.id, tempUuid.id, sizeof(tempUuid.id));
1908 memcpy(gDoxm->owner.id, tempUuid.id, sizeof(tempUuid.id));
1909 memcpy(gDoxm->rownerID.id, tempUuid.id, sizeof(tempUuid.id));
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);