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"
29 #include "oic_malloc.h"
30 #include "payload_logging.h"
33 #include "ocpayload.h"
34 #include "ocpayloadcbor.h"
35 #include "cainterface.h"
36 #include "ocserverrequest.h"
37 #include "resourcemanager.h"
38 #include "doxmresource.h"
39 #include "pstatresource.h"
40 #include "aclresource.h"
41 #include "amaclresource.h"
42 #include "pconfresource.h"
43 #include "dpairingresource.h"
44 #include "psinterface.h"
45 #include "srmresourcestrings.h"
46 #include "securevirtualresourcetypes.h"
47 #include "credresource.h"
48 #include "srmutility.h"
49 #include "pinoxmcommon.h"
50 #include "oxmverifycommon.h"
53 #include "oic_string.h"
55 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
56 #include "pkix_interface.h"
57 #include "ca_adapter_net_ssl.h"
60 #define TAG "OIC_SRM_DOXM"
61 #define CHAR_ZERO ('0')
63 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
64 * The value of payload size is increased until reaching belox max cbor size. */
65 static const uint16_t CBOR_SIZE = 512;
67 /** Max cbor size payload. */
68 static const uint16_t CBOR_MAX_SIZE = 4400;
70 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
71 /** MAX uuid seed size */
72 #define MAX_UUID_SEED_SIZE (64)
73 /** MIN uuid seed size */
74 #define MIN_UUID_SEED_SIZE (8)
76 /** Buffer to save the seed of device UUID */
77 static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
78 static size_t gUuidSeedSize = 0;
82 #define MAX_SUBOWNER_SIZE (64)
83 #define MIN_SUBOWNER_SIZE (1)
84 #define DEFAULT_SUBOWNER_SIZE (32)
86 static size_t gMaxSubOwnerSize = DEFAULT_SUBOWNER_SIZE;
89 typedef enum ConfirmState{
90 CONFIRM_STATE_READY = 0,
91 CONFIRM_STATE_WAIT = 1,
92 CONFIRM_STATE_ACCEPTED = 2,
93 CONFIRM_STATE_DENIED = 3
96 static OicSecDoxm_t *gDoxm = NULL;
97 static oc_mutex g_mutexDoxm = NULL;
98 static bool g_isDoxmNull = false;
99 static OCResourceHandle gDoxmHandle = NULL;
100 static oc_mutex g_mutexWait;
101 static oc_thread g_waitConfirmThreadId;
103 static InformOxmSelectedCallback_t g_InformOxmSelectedCallback = NULL;
105 static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
106 static OicSecDoxm_t gDefaultDoxm =
108 NULL, /* OicUrn_t *oxmType */
109 0, /* size_t oxmTypeLen */
110 &gOicSecDoxmJustWorks, /* uint16_t *oxm */
111 1, /* size_t oxmLen */
112 OIC_JUST_WORKS, /* uint16_t oxmSel */
113 SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
114 false, /* bool owned */
115 {.id = {0}}, /* OicUuid_t deviceID */
116 false, /* bool dpc */
117 {.id = {0}}, /* OicUuid_t owner */
118 #ifdef MULTIPLE_OWNER
119 NULL, /* OicSecSubOwner_t sub-owner list */
120 NULL, /* OicSecMomType_t multiple owner mode */
121 #endif //MULTIPLE_OWNER
122 {.id = {0}}, /* OicUuid_t rownerID */
125 static uint16_t gConfirmMsgId = 0;
126 static ConfirmState_t gConfirmState = CONFIRM_STATE_READY;
128 static uint8_t gEmptyUuid[UUID_LENGTH] = {0};
131 * This method is internal method.
132 * the param roParsed is optionally used to know whether cborPayload has
133 * at least read only property value or not.
135 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
136 OicSecDoxm_t **doxm, bool *roParsed);
138 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
143 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
145 OICFree(doxm->oxmType[i]);
147 OICFree(doxm->oxmType);
152 #ifdef MULTIPLE_OWNER
156 //clean sub-owner list
157 if(NULL != doxm->subOwners)
159 OicSecSubOwner_t* subowner = NULL;
160 OicSecSubOwner_t* temp = NULL;
161 LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
163 LL_DELETE(doxm->subOwners, subowner);
167 #endif //MULTIPLE_OWNER
175 oc_mutex_free(g_mutexDoxm);
180 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm, uint8_t **payload, size_t *size,
183 if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
185 return OC_STACK_INVALID_PARAM;
187 size_t cborLen = *size;
195 OCStackResult ret = OC_STACK_ERROR;
199 char* strUuid = NULL;
201 int64_t cborEncoderResult = CborNoError;
203 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
204 VERIFY_NON_NULL(TAG, outPayload, ERROR);
205 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
207 cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
208 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
210 //OxmType -- Not Mandatory
211 if (doxm->oxmTypeLen > 0)
214 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_TYPE_NAME,
215 strlen(OIC_JSON_OXM_TYPE_NAME));
216 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Tag.");
217 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxmType, doxm->oxmTypeLen);
218 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Array.");
220 for (size_t i = 0; i < doxm->oxmTypeLen; i++)
222 cborEncoderResult = cbor_encode_text_string(&oxmType, doxm->oxmType[i],
223 strlen(doxm->oxmType[i]));
224 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmType Value.");
226 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxmType);
227 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmType.");
230 //Oxm -- Not Mandatory
231 if (doxm->oxmLen > 0 && false == rwOnly)
234 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
235 strlen(OIC_JSON_OXMS_NAME));
236 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Tag.");
237 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
238 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Array.");
240 for (size_t i = 0; i < doxm->oxmLen; i++)
242 cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
243 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmName Value");
245 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
246 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxmName.");
249 //OxmSel -- Mandatory
250 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
251 strlen(OIC_JSON_OXM_SEL_NAME));
252 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Tag.");
253 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
254 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Sel Value.");
259 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
260 strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
261 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag");
262 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
263 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
267 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OWNED_NAME,
268 strlen(OIC_JSON_OWNED_NAME));
269 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Tag.");
270 cborEncoderResult = cbor_encode_boolean(&doxmMap, doxm->owned);
271 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owned Value.");
275 //DeviceId -- Mandatory
276 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
277 strlen(OIC_JSON_DEVICE_ID_NAME));
278 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
279 ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
280 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
281 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
282 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
287 #ifdef MULTIPLE_OWNER
288 //Device SubOwnerID -- Not Mandatory
291 size_t subOwnerLen = 0;
292 OicSecSubOwner_t* subOwner = NULL;
293 LL_FOREACH(doxm->subOwners, subOwner)
298 CborEncoder subOwners;
299 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
300 strlen(OIC_JSON_SUBOWNERID_NAME));
301 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
302 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
303 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
306 LL_FOREACH(doxm->subOwners, subOwner)
308 char* strUuid = NULL;
309 ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
310 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
311 cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
313 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
315 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
316 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
319 //Multiple Owner Mode -- Not Mandatory
322 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
323 strlen(OIC_JSON_MOM_NAME));
324 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
325 cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
326 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
328 #endif //MULTIPLE_OWNER
330 //devownerid -- Mandatory
331 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
332 strlen(OIC_JSON_DEVOWNERID_NAME));
333 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Tag.");
334 ret = ConvertUuidToStr(&doxm->owner, &strUuid);
335 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
336 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
337 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owner Id Value.");
341 //ROwner -- Mandatory
342 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
343 strlen(OIC_JSON_ROWNERID_NAME));
344 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
345 ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
346 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
347 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
348 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
354 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
355 strlen(OIC_JSON_RT_NAME));
356 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
357 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
358 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
359 for (size_t i = 0; i < 1; i++)
361 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
362 strlen(OIC_RSRC_TYPE_SEC_DOXM));
363 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
365 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
366 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
370 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
371 strlen(OIC_JSON_IF_NAME));
372 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
373 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
374 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
375 for (size_t i = 0; i < 1; i++)
377 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
378 strlen(OC_RSRVD_INTERFACE_DEFAULT));
379 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
381 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
382 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
384 cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
385 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
387 if (CborNoError == cborEncoderResult)
389 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
390 *payload = outPayload;
394 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
396 OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
397 // reallocate and try again!
400 // Since the allocated initial memory failed, double the memory.
401 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
402 OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
403 cborEncoderResult = CborNoError;
404 ret = DoxmToCBORPayload(doxm, payload, &cborLen, rwOnly);
408 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
414 ret = OC_STACK_ERROR;
420 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
421 OicSecDoxm_t **secDoxm)
423 return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL);
426 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
427 OicSecDoxm_t **secDoxm, bool *roParsed)
429 if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
431 return OC_STACK_INVALID_PARAM;
434 OCStackResult ret = OC_STACK_ERROR;
438 CborError cborFindResult = CborNoError;
439 char* strUuid = NULL;
443 cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
445 OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
446 VERIFY_NON_NULL(TAG, doxm, ERROR);
448 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_TYPE_NAME, &doxmMap);
449 //OxmType -- not Mandatory
450 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
454 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
455 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
456 VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
458 doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
459 VERIFY_NON_NULL(TAG, doxm->oxmType, ERROR);
461 cborFindResult = cbor_value_enter_container(&doxmMap, &oxmType);
462 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmType Array.")
466 while (cbor_value_is_valid(&oxmType) && cbor_value_is_text_string(&oxmType))
468 cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
470 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
471 cborFindResult = cbor_value_advance(&oxmType);
472 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
476 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
477 //Oxm -- not Mandatory
478 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
481 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
482 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
483 VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
485 doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
486 VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
488 cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
489 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxmName Array.")
492 while (cbor_value_is_valid(&oxm) && cbor_value_is_integer(&oxm))
496 cborFindResult = cbor_value_get_int(&oxm, &tmp);
497 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName Value")
498 doxm->oxm[i++] = (OicSecOxm_t)tmp;
499 cborFindResult = cbor_value_advance(&oxm);
500 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmName.")
510 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
511 doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
512 VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
513 doxm->oxmLen = gDoxm->oxmLen;
514 for (size_t i = 0; i < gDoxm->oxmLen; i++)
516 doxm->oxm[i] = gDoxm->oxm[i];
520 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
521 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
525 cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
526 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
527 doxm->oxmSel = (OicSecOxm_t)oxmSel;
529 else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
531 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
532 doxm->oxmSel = gDoxm->oxmSel;
535 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
536 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
540 cborFindResult = cbor_value_get_int(&doxmMap, &sct);
541 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
542 doxm->sct = (OicSecCredType_t)sct;
549 else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
551 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
552 doxm->sct = gDoxm->sct;
555 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
556 if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
558 cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
559 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
561 else // PUT/POST JSON may not have owned so set it to the gDomx->owned
563 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
564 doxm->owned = gDoxm->owned;
567 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
568 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
570 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
571 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
572 ret = ConvertStrToUuid(strUuid , &doxm->deviceID);
573 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
579 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
580 memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
583 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
584 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
586 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
587 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
588 ret = ConvertStrToUuid(strUuid , &doxm->owner);
589 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
595 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
596 memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
599 #ifdef MULTIPLE_OWNER
600 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
601 if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
604 cborFindResult = cbor_value_get_int(&doxmMap, &mode);
605 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
606 if(NULL == doxm->mom)
608 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
609 VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
611 doxm->mom->mode = (OicSecMomType_t)mode;
613 else if(NULL != gDoxm && NULL != gDoxm->mom)
615 // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
616 if(NULL == doxm->mom)
618 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
619 VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
621 doxm->mom->mode = gDoxm->mom->mode;
624 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
625 if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
627 size_t subOwnerLen = 0;
628 CborValue subOwnerCbor;
629 cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
630 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
631 VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
633 cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
634 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
636 while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
638 OCStackResult convertRes = OC_STACK_ERROR;
639 OicSecSubOwner_t* subOwner = NULL;
640 char* strUuid = NULL;
643 cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
644 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
646 subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
647 VERIFY_NON_NULL(TAG, subOwner, ERROR);
649 convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
650 VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
651 subOwner->status = MOT_STATUS_DONE;
652 LL_APPEND(doxm->subOwners, subOwner);
654 cborFindResult = cbor_value_advance(&subOwnerCbor);
655 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
658 else if(NULL != gDoxm && NULL != gDoxm->subOwners)
660 // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
661 OicSecSubOwner_t* subOwnerItor = NULL;
662 LL_FOREACH(gDoxm->subOwners, subOwnerItor)
664 OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
665 VERIFY_NON_NULL(TAG, subOwnerId, ERROR);
667 memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
668 subOwnerId->status = MOT_STATUS_DONE;
670 LL_APPEND(doxm->subOwners, subOwnerId);
673 #endif //MULTIPLE_OWNER
675 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
676 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
678 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
679 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Value.");
680 ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
681 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
687 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
688 memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
695 if (CborNoError != cborFindResult)
697 OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
698 DeleteDoxmBinData(doxm);
701 ret = OC_STACK_ERROR;
707 * @todo document this function including why code might need to call this.
708 * The current suspicion is that it's not being called as much as it should.
710 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
716 // Convert Doxm data into CBOR for update to persistent storage
717 uint8_t *payload = NULL;
719 OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size, false);
720 if (payload && (OC_STACK_OK == res)
721 && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
729 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
738 static bool ValidateQuery(const char * query)
740 // Send doxm resource data if the state of doxm resource
741 // matches with the query parameters.
742 // else send doxm resource data as NULL
743 // TODO Remove this check and rely on Policy Engine
744 // and Provisioning Mode to enforce provisioning-state
745 // access rules. Eventually, the PE and PM code will
746 // not send a request to the /doxm Entity Handler at all
747 // if it should not respond.
748 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
754 bool bOwnedQry = false; // does querystring contains 'owned' query ?
755 bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
756 bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
757 bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
758 bool bInterfaceQry = false; // does querystring contains 'if' query ?
759 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
760 #ifdef MULTIPLE_OWNER
761 bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
762 #endif //MULTIPLE_OWNER
764 OicParseQueryIter_t parseIter = {.attrPos = NULL};
766 ParseQueryIterInit((unsigned char*)query, &parseIter);
768 while (GetNextQuery(&parseIter))
770 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
773 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
778 else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
785 #ifdef MULTIPLE_OWNER
786 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
788 OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
789 if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
791 if(GetNextQuery(&parseIter))
793 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
795 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
805 #endif //MULTIPLE_OWNER
807 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
810 OicUuid_t subject = {.id={0}};
812 memcpy(subject.id, parseIter.valPos, parseIter.valLen);
813 if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
815 bDeviceIDMatch = true;
819 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
821 bInterfaceQry = true;
822 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
824 bInterfaceMatch = true;
826 return (bInterfaceQry ? bInterfaceMatch: true);
830 return ((bOwnedQry ? bOwnedMatch : true) &&
831 (bDeviceIDQry ? bDeviceIDMatch : true));
834 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
836 OCEntityHandlerResult ehRet = OC_EH_OK;
838 OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
840 //Checking if Get request is a query.
841 if (ehRequest->query)
843 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
844 OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
845 if (!ValidateQuery(ehRequest->query))
852 * For GET or Valid Query request return doxm resource CBOR payload.
853 * For non-valid query return NULL json payload.
854 * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
855 * return valid doxm resource json.
857 uint8_t *payload = NULL;
860 if (ehRet == OC_EH_OK)
862 if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size, false))
864 OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
868 OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
869 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
871 // Send response payload to request originator
872 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
873 OC_EH_OK : OC_EH_ERROR;
880 static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
885 dst->oxmSel = src->oxmSel;
888 memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
891 memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
894 memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
896 //Update owned status
897 if(dst->owned != src->owned)
899 dst->owned = src->owned;
902 #ifdef MULTIPLE_OWNER
905 OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
908 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
911 dst->mom->mode = src->mom->mode;
915 #endif //MULTIPLE_OWNER
919 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
920 #ifdef MULTIPLE_OWNER
922 * Internal function to get number of sub-owner
924 static size_t GetSubOwnerSize()
926 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
928 size_t numberOfSubOwner = 0;
930 if (gDoxm && gDoxm->subOwners)
932 OicSecSubOwner_t* subowner = NULL;
933 LL_FOREACH(gDoxm->subOwners, subowner)
939 OIC_LOG_V(DEBUG, TAG, "Numer of registered sub-owner=%zd", numberOfSubOwner);
940 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
942 return numberOfSubOwner;
946 * Callback function to handle MOT DTLS handshake result.
947 * @param[out] endpoint remote device information.
948 * @param[out] errorInfo CA Error information.
950 void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *endpoint,
951 const CAErrorInfo_t *errorInfo)
953 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
954 if (!endpoint || !errorInfo)
956 OIC_LOG(ERROR, TAG, "Invalid param");
962 OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
966 if ((CA_STATUS_OK == errorInfo->result) && (true == gDoxm->owned)
967 && (OIC_PRECONFIG_PIN == gDoxm->oxmSel) && (NULL != gDoxm->mom)
968 && (OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode) && (CA_ADAPTER_TCP != endpoint->adapter))
970 OIC_LOG_V(INFO, TAG, "DTLS session established for sub-owner authentication : (%s:%d)",
971 endpoint->addr, endpoint->port);
973 const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(endpoint);
974 if (authenticatedSubOwnerInfo)
976 if (0 == memcmp(authenticatedSubOwnerInfo->identity.id, gDoxm->owner.id,
977 authenticatedSubOwnerInfo->identity.id_length))
979 OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
983 OicSecSubOwner_t* subOwnerInst = NULL;
984 LL_FOREACH(gDoxm->subOwners, subOwnerInst)
986 if(0 == memcmp(subOwnerInst->uuid.id,
987 authenticatedSubOwnerInfo->identity.id,
988 authenticatedSubOwnerInfo->identity.id_length))
994 if (NULL == subOwnerInst)
996 subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
999 char* strUuid = NULL;
1000 if (OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
1002 OIC_LOG(WARNING, TAG, "ConvertUuidToStr error");
1004 OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
1006 if (gMaxSubOwnerSize > GetSubOwnerSize())
1008 memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id,
1009 authenticatedSubOwnerInfo->identity.id_length);
1010 LL_APPEND(gDoxm->subOwners, subOwnerInst);
1011 if (!UpdatePersistentStorage(gDoxm))
1013 OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
1018 OIC_LOG_V(ERROR, TAG, "Number of sub-owner exceeded : (MAX SIZE=%zd)", gMaxSubOwnerSize);
1020 //Close DTLS session
1021 if (CA_STATUS_OK != CAcloseSslSession(endpoint))
1023 OIC_LOG_V(ERROR, TAG, "CAcloseSslSession error for [%s:%d]", endpoint->addr, endpoint->port);
1027 if (OC_STACK_RESOURCE_DELETED != RemoveCredential(&subOwnerInst->uuid))
1029 OIC_LOG_V(ERROR, TAG, "RemoveCredential error for [%s]", strUuid);
1032 // TODO: How to send error to client side?
1041 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
1043 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
1046 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1048 #endif //MULTIPLE_OWNER
1049 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1052 * Function to validate oxmsel with oxms.
1054 * @param[in] supportedMethods Array of supported methods
1055 * @param[in] numberOfMethods number of supported methods
1056 * @param[out] selectedMethod Selected methods
1057 * @return TRUE on success
1059 static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
1060 size_t numberOfMethods, OicSecOxm_t *selectedMethod)
1062 bool isValidOxmsel = false;
1064 OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
1065 if (numberOfMethods == 0 || !supportedMethods)
1067 OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
1068 return isValidOxmsel;
1071 for (size_t i = 0; i < numberOfMethods; i++)
1073 if (*selectedMethod == supportedMethods[i])
1075 isValidOxmsel = true;
1081 OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
1082 return isValidOxmsel;
1085 OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
1087 return isValidOxmsel;
1090 void SetInformOxmSelCB(InformOxmSelectedCallback_t informOxmSelCB)
1092 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1093 g_InformOxmSelectedCallback = informOxmSelCB;
1094 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1097 void UnsetInformOxmSelCB()
1099 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1100 g_InformOxmSelectedCallback = NULL;
1101 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1104 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1105 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest);
1107 static void DestroyEntityHandlerRequest(OCEntityHandlerRequest * ehRequest)
1109 if (ehRequest == NULL) {
1110 OIC_LOG(WARNING, TAG, "ehRequest is NULL");
1114 OICFree(ehRequest->query);
1116 if (ehRequest->payload) {
1117 OICFree(((OCSecurityPayload *)ehRequest->payload)->securityData);
1118 OICFree(ehRequest->payload);
1124 void * WaitConfirm(OCEntityHandlerRequest * ehRequest)
1126 bool confirmResult = false, confirmState = false;
1128 oc_mutex_lock(g_mutexWait);
1129 oc_cond_wait(g_condWait, g_mutexWait);
1130 oc_cond_free(g_condWait);
1131 oc_mutex_free(g_mutexWait);
1133 GetAsyncVerifyUserResult(&confirmResult, &confirmState);
1134 if (confirmResult == true)
1136 gConfirmState = CONFIRM_STATE_ACCEPTED;
1137 HandleDoxmPostRequest(ehRequest);
1142 gConfirmState = CONFIRM_STATE_DENIED;
1143 HandleDoxmPostRequest(ehRequest);
1147 DestroyEntityHandlerRequest(ehRequest);
1152 static OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
1154 OIC_LOG(INFO, TAG, "Copying received request for slow response");
1156 if (!entityHandlerRequest)
1158 OIC_LOG_V(ERROR, TAG, "%s: entityHandlerRequest is NULL", __func__);
1162 OCEntityHandlerRequest *copyOfRequest =
1163 (OCEntityHandlerRequest *)OICCalloc(1, sizeof(OCEntityHandlerRequest));
1166 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1170 memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
1172 if (entityHandlerRequest->query)
1174 copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
1175 if(!copyOfRequest->query)
1177 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1178 OICFree(copyOfRequest);
1183 if (entityHandlerRequest->payload)
1185 copyOfRequest->payload =
1186 (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1187 if(!copyOfRequest->payload)
1189 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1190 OICFree(copyOfRequest->query);
1191 OICFree(copyOfRequest);
1195 if (((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize)
1197 ((OCSecurityPayload *)copyOfRequest->payload)->securityData =
1198 (uint8_t *)OICCalloc(1, ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
1199 if(!((OCSecurityPayload *)copyOfRequest->payload)->securityData)
1201 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1202 OICFree(copyOfRequest->payload);
1203 OICFree(copyOfRequest->query);
1204 OICFree(copyOfRequest);
1208 memcpy(((OCSecurityPayload *)copyOfRequest->payload)->securityData,
1209 ((OCSecurityPayload *)entityHandlerRequest->payload)->securityData,
1210 ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
1212 ((OCSecurityPayload *)(copyOfRequest->payload))->payloadSize =
1213 ((OCSecurityPayload *)(entityHandlerRequest->payload))->payloadSize;
1216 copyOfRequest->payload->type = entityHandlerRequest->payload->type;
1217 copyOfRequest->messageID = entityHandlerRequest->messageID;
1220 // Ignore vendor specific header options for example
1221 copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
1222 copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
1226 OIC_LOG(INFO, TAG, "Copied client request");
1230 OIC_LOG(ERROR, TAG, "Error copying client request");
1232 return copyOfRequest;
1234 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1236 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
1238 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
1239 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1240 OicUuid_t emptyOwner = {.id = {0} };
1241 static uint16_t previousMsgId = 0;
1242 bool isDuplicatedMsg = false;
1245 * Convert CBOR Doxm data into binary. This will also validate
1246 * the Doxm data received.
1248 OicSecDoxm_t *newDoxm = NULL;
1250 if (ehRequest->payload)
1252 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1253 size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1254 bool roParsed = false;
1255 OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
1256 if (newDoxm && OC_STACK_OK == res)
1259 * message ID is supported for CoAP over UDP only according to RFC 7252
1260 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1261 * In case of other transport adapter, duplicate message check is not required.
1263 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1264 previousMsgId == ehRequest->messageID)
1266 isDuplicatedMsg = true;
1269 if (isDuplicatedMsg && ehRequest->messageID == gConfirmMsgId)
1271 if (CONFIRM_STATE_WAIT == gConfirmState)
1273 OIC_LOG(DEBUG, TAG, "Confirm callback already invoked.");
1274 OIC_LOG(DEBUG, TAG, "This request will be ignored.");
1275 DeleteDoxmBinData(newDoxm);
1280 OIC_LOG_V(DEBUG, TAG, "Confirm request already done, Confirm Result = %s", (CONFIRM_STATE_ACCEPTED == gConfirmState ? "ACCEPTED" : "DENIED"));
1281 ehRet = (CONFIRM_STATE_ACCEPTED == gConfirmState ? OC_EH_OK : OC_EH_NOT_ACCEPTABLE);
1286 // Check request on RO property
1287 if (true == roParsed)
1289 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
1290 ehRet = OC_EH_NOT_ACCEPTABLE;
1294 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
1297 if (true == gDoxm->owned)
1299 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1301 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1302 ehRet = OC_EH_NOT_ACCEPTABLE;
1305 //Update gDoxm based on newDoxm
1306 updateWriteableProperty(newDoxm, gDoxm);
1308 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1309 #ifdef MULTIPLE_OWNER
1313 if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1315 CAResult_t caRes = CA_STATUS_FAILED;
1316 if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1318 caRes = CAEnableAnonECDHCipherSuite(false);
1319 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1320 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1322 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, ehRequest->devAddr.adapter);
1323 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1324 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1326 //Set the device id to derive temporal PSK
1327 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1331 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1334 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1338 //if MOM is disabled, revert the DTLS handshake callback
1339 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1341 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1346 if(newDoxm->subOwners)
1348 OicSecSubOwner_t* subowner = NULL;
1349 OicSecSubOwner_t* temp = NULL;
1351 OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1353 if(gDoxm->subOwners)
1355 LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1357 LL_DELETE(gDoxm->subOwners, subowner);
1364 LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1366 LL_DELETE(newDoxm->subOwners, subowner);
1367 LL_APPEND(gDoxm->subOwners, subowner);
1370 #endif //MULTIPLE_OWNER
1371 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1373 //Update new state in persistent storage
1374 if (UpdatePersistentStorage(gDoxm) == true)
1380 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1381 ehRet = OC_EH_ERROR;
1387 if ((false == gDoxm->owned) && (false == newDoxm->owned))
1389 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1391 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1392 ehRet = OC_EH_NOT_ACCEPTABLE;
1395 if (g_InformOxmSelectedCallback)
1397 g_InformOxmSelectedCallback(newDoxm->oxmSel);
1400 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1401 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1403 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1404 NULL, OIC_OTM_STARTED);
1408 OIC_LOG_V(INFO, TAG, "%s: request owner not empty",__func__);
1409 char* strUuid = NULL;
1410 if (OC_STACK_OK == ConvertUuidToStr(&newDoxm->owner, &strUuid))
1412 OIC_LOG_V(INFO, TAG, "%s: request owner: %s",__func__, strUuid);
1418 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1421 * If current state of the device is un-owned, enable
1422 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1423 * tool can initiate JUST_WORKS ownership transfer process.
1425 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1427 gDoxm->oxmSel = newDoxm->oxmSel;
1428 //Update new state in persistent storage
1429 if ((UpdatePersistentStorage(gDoxm) == true))
1435 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1436 ehRet = OC_EH_ERROR;
1439 OIC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
1440 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1441 ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1442 #endif // __WITH_DTLS__ or __WITH_TLS__
1447 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1448 //Save the owner's UUID to derive owner credential
1449 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1451 // Update new state in persistent storage
1452 if (true == UpdatePersistentStorage(gDoxm))
1458 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1459 ehRet = OC_EH_ERROR;
1464 * Disable anonymous ECDH cipher in tinyDTLS since device is now
1467 CAResult_t caRes = CA_STATUS_OK;
1468 caRes = CAEnableAnonECDHCipherSuite(false);
1469 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1470 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1472 //In case of Mutual Verified Just-Works, verify mutualVerifNum
1473 if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1474 false == isDuplicatedMsg)
1476 uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1477 uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1478 OicUuid_t deviceID = {.id = {0}};
1480 //Generate mutualVerifNum
1481 OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1483 char label[LABEL_LEN] = {0};
1484 snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1485 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1487 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1488 ehRet = OC_EH_ERROR;
1493 CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1496 gDoxm->owner.id, sizeof(gDoxm->owner.id),
1497 gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1498 preMutualVerifNum, OWNER_PSK_LENGTH_128);
1499 if (CA_STATUS_OK != pskRet)
1501 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1502 ehRet = OC_EH_ERROR;
1507 memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1508 sizeof(mutualVerifNum));
1510 gConfirmMsgId = ehRequest->messageID;
1511 gConfirmState = CONFIRM_STATE_WAIT;
1512 //Wait for user confirmation
1513 if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1515 ehRet = OC_EH_NOT_ACCEPTABLE;
1516 gConfirmState = CONFIRM_STATE_DENIED;
1521 gConfirmState = CONFIRM_STATE_ACCEPTED;
1525 #endif // __WITH_DTLS__ or __WITH_TLS__
1528 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1531 * If current state of the device is un-owned, enable
1532 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1533 * tool can initiate JUST_WORKS ownership transfer process.
1535 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1537 gDoxm->oxmSel = newDoxm->oxmSel;
1538 //Update new state in persistent storage
1539 if ((UpdatePersistentStorage(gDoxm) == true))
1545 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1546 ehRet = OC_EH_ERROR;
1549 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1550 CAResult_t caRes = CA_STATUS_OK;
1552 caRes = CAEnableAnonECDHCipherSuite(false);
1553 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1554 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1556 caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1557 ehRequest->devAddr.adapter);
1558 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1560 if (!isDuplicatedMsg)
1562 char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1563 if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1565 //Set the device id to derive temporal PSK
1566 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1569 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1570 * Credential should not be saved into SVR.
1571 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1573 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1574 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1579 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1580 ehRet = OC_EH_ERROR;
1583 #endif // __WITH_DTLS__ or __WITH_TLS__
1585 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1588 //Save the owner's UUID to derive owner credential
1589 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1591 // In case of random-pin based OTM, close the PIN display if callback is registered.
1592 if (!isDuplicatedMsg)
1597 //Update new state in persistent storage
1598 if (UpdatePersistentStorage(gDoxm) == true)
1604 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1605 ehRet = OC_EH_ERROR;
1608 #endif // __WITH_DTLS__ or __WITH_TLS__
1610 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1611 else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1613 if (CONFIRM_STATE_ACCEPTED != gConfirmState && CONFIRM_STATE_DENIED != gConfirmState)
1615 //Get user confirmation
1616 if (false == newDoxm->owned &&
1617 false == isDuplicatedMsg &&
1618 memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1620 gConfirmMsgId = ehRequest->messageID;
1621 gConfirmState = CONFIRM_STATE_WAIT;
1623 if (OC_STACK_OK != VerifyUserConfirm())
1625 if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1627 ehRet = OC_EH_NOT_ACCEPTABLE;
1628 gConfirmState = CONFIRM_STATE_DENIED;
1634 OCEntityHandlerRequest * ehRequestCopy = CopyRequest(ehRequest);
1635 VERIFY_NON_NULL(TAG, ehRequestCopy, ERROR);
1637 g_condWait = oc_cond_new();
1638 g_mutexWait = oc_mutex_new();
1639 if (oc_thread_new (&g_waitConfirmThreadId, WaitConfirm, ehRequestCopy))
1641 oc_thread_detach(g_waitConfirmThreadId);
1647 else if (CONFIRM_STATE_DENIED == gConfirmState)
1649 ehRet = OC_EH_NOT_ACCEPTABLE;
1653 //Save the owner's UUID to derive owner credential
1654 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1655 gDoxm->oxmSel = newDoxm->oxmSel;
1656 //Update new state in persistent storage
1657 if (UpdatePersistentStorage(gDoxm))
1663 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1664 ehRet = OC_EH_ERROR;
1666 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1667 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1668 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1670 //Unset pre-selected ciphersuite, if any
1671 caRes = CASelectCipherSuite(0, ehRequest->devAddr.adapter);
1672 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1673 OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
1675 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1676 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1678 #endif // __WITH_DTLS__ or __WITH_TLS__
1682 * When current state of the device is un-owned and Provisioning
1683 * Tool is attempting to change the state to 'Owned' with a
1684 * qualified value for the field 'Owner'
1686 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1687 (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1689 //Change the SVR's resource owner as owner device.
1690 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1691 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1693 ehRet = OC_EH_ERROR;
1696 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1697 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1699 ehRet = OC_EH_ERROR;
1702 ownerRes = SetCredRownerId(&gDoxm->owner);
1703 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1705 ehRet = OC_EH_ERROR;
1708 ownerRes = SetPstatRownerId(&gDoxm->owner);
1709 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1711 ehRet = OC_EH_ERROR;
1715 gDoxm->owned = true;
1716 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1718 // Update new state in persistent storage
1719 if (UpdatePersistentStorage(gDoxm))
1721 //Update default ACE of security resource to prevent anonymous user access.
1722 if(OC_STACK_OK == UpdateDefaultSecProvACE())
1728 OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1729 ehRet = OC_EH_ERROR;
1734 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1735 ehRet = OC_EH_ERROR;
1737 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1738 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1739 OIC_CON_MFG_CERT== gDoxm->oxmSel)
1741 CAregisterPkixInfoHandler(GetPkixInfo);
1742 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1745 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1746 &gDoxm->owner, OIC_OTM_DONE);
1747 #endif // __WITH_DTLS__ or __WITH_TLS__
1753 if(OC_EH_OK != ehRet)
1756 * If some error is occured while ownership transfer,
1757 * ownership transfer related resource should be revert back to initial status.
1763 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1765 if (!isDuplicatedMsg)
1767 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1768 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1769 NULL, OIC_OTM_ERROR);
1771 RestoreDoxmToInitState();
1772 RestorePstatToInitState();
1773 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1779 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1783 previousMsgId = ehRequest->messageID;
1785 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1786 CAEndpoint_t peer = {0};
1787 OCDevAddr devAddr = ehRequest->devAddr;
1789 memcpy(&peer.addr, &devAddr.addr, sizeof(peer.addr));
1790 peer.port = devAddr.port;
1791 peer.adapter = (CATransportAdapter_t)devAddr.adapter;
1793 if ((devAddr.flags & OC_FLAG_SECURE) && (false == CAIsExistSslPeer(&peer)))
1795 OIC_LOG_V(WARNING, TAG, "Not Exist Peer");
1800 //Send payload to request originator
1801 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1802 OC_EH_OK : OC_EH_ERROR;
1805 //Send payload to request originator
1806 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1807 OC_EH_OK : OC_EH_ERROR;
1810 DeleteDoxmBinData(newDoxm);
1815 #ifdef MULTIPLE_OWNER
1816 static OCEntityHandlerResult HandleDoxmDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1818 OIC_LOG(DEBUG, TAG, "Processing DoxmDeleteRequest");
1820 OCEntityHandlerResult ehRet = OC_EH_BAD_REQ;
1822 if (NULL == ehRequest->query)
1827 OicParseQueryIter_t parseIter = { .attrPos=NULL };
1828 OicUuid_t subject = {.id={0}};
1830 //Parsing REST query to get the subject
1831 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1832 while (GetNextQuery(&parseIter))
1834 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBOWNERID_NAME,
1835 parseIter.attrLen) == 0)
1837 if (0 == strncmp((const char*)parseIter.valPos, WILDCARD_RESOURCE_URI,
1838 strlen(WILDCARD_RESOURCE_URI)))
1840 if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&WILDCARD_SUBJECT_ID))
1842 ehRet = OC_EH_RESOURCE_DELETED;
1847 OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1848 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1850 if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&subject))
1852 ehRet = OC_EH_RESOURCE_DELETED;
1858 //Send response to request originator
1859 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1860 OC_EH_OK : OC_EH_ERROR;
1866 #endif //MULTIPLE_OWNER
1868 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1869 OCEntityHandlerRequest * ehRequest,
1870 void* callbackParam)
1872 (void)callbackParam;
1873 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1875 if(NULL == ehRequest)
1880 oc_mutex_lock(g_mutexDoxm);
1884 oc_mutex_unlock(g_mutexDoxm);
1885 return OC_EH_SERVICE_UNAVAILABLE;
1888 if (flag & OC_REQUEST_FLAG)
1890 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1892 switch (ehRequest->method)
1895 ehRet = HandleDoxmGetRequest(ehRequest);
1899 ehRet = HandleDoxmPostRequest(ehRequest);
1902 #ifdef MULTIPLE_OWNER
1903 case OC_REST_DELETE:
1904 ehRet = HandleDoxmDeleteRequest(ehRequest);
1906 #endif //MULTIPLE_OWNER
1909 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1910 OC_EH_OK : OC_EH_ERROR;
1914 oc_mutex_unlock(g_mutexDoxm);
1920 OCStackResult CreateDoxmResource()
1922 OCStackResult ret = OCCreateResource(&gDoxmHandle,
1923 OIC_RSRC_TYPE_SEC_DOXM,
1924 OC_RSRVD_INTERFACE_DEFAULT,
1931 if (OC_STACK_OK != ret)
1933 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1934 DeInitDoxmResource();
1940 * Checks if DeviceID is generated during provisioning for the new device.
1941 * If DeviceID is NULL then generates the new DeviceID.
1942 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1944 static OCStackResult CheckDeviceID()
1946 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1948 OCStackResult ret = OC_STACK_ERROR;
1949 bool validId = false;
1953 OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
1954 return OC_STACK_INVALID_PARAM;
1957 for (uint8_t i = 0; i < UUID_LENGTH; i++)
1959 if (gDoxm->deviceID.id[i] != 0)
1968 char* strUuid = NULL;
1969 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1970 //If seed value is exist, generate UUID using seed with SHA256
1971 if (0 != gUuidSeedSize)
1973 uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1974 mbedtls_md_context_t sha_ctx;
1977 OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1978 OIC_LOG(DEBUG, TAG, "Seed value : ");
1979 OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1981 mbedtls_md_init( &sha_ctx );
1982 mbedret = mbedtls_md_setup( &sha_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 );
1985 mbedtls_md_starts( &sha_ctx );
1986 mbedtls_md_update( &sha_ctx, gUuidSeed, gUuidSeedSize);
1987 mbedtls_md_finish(&sha_ctx, (unsigned char*)hashVal);
1988 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1993 OIC_LOG_V(ERROR, TAG, "mbedtls_md_setup() returned -0x%04x\n", -mbedret);
1994 ret = OC_STACK_ERROR;
1996 mbedtls_md_free( &sha_ctx );
2000 if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
2002 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
2003 return OC_STACK_ERROR;
2008 if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
2010 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
2016 if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
2018 OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
2023 OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
2027 if (!UpdatePersistentStorage(gDoxm))
2029 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
2030 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
2038 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
2044 * Get the default value.
2046 * @return the default value of doxm, @ref OicSecDoxm_t.
2048 static OicSecDoxm_t* GetDoxmDefault()
2050 OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
2051 return &gDefaultDoxm;
2054 const OicSecDoxm_t* GetDoxmResourceData()
2059 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2061 * Internal API to prepare MOT
2063 static void PrepareMOT(const OicSecDoxm_t* doxm)
2065 OIC_LOG(INFO, TAG, "IN PrepareMOT");
2066 VERIFY_NON_NULL(TAG, doxm, ERROR);
2068 if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
2070 CAResult_t caRes = CA_STATUS_FAILED;
2072 OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
2074 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
2076 caRes = CAEnableAnonECDHCipherSuite(false);
2077 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
2078 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
2080 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
2081 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
2083 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
2084 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
2086 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
2088 //Set the device id to derive temporal PSK
2089 SetUuidForPinBasedOxm(&doxm->deviceID);
2093 OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
2097 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
2100 OIC_LOG(INFO, TAG, "OUT PrepareMOT");
2103 OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
2105 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2107 OCStackResult InitDoxmResource()
2109 OCStackResult ret = OC_STACK_ERROR;
2113 g_mutexDoxm = oc_mutex_new();
2116 return OC_STACK_ERROR;
2120 gConfirmState = CONFIRM_STATE_READY;
2123 //Read DOXM resource from PS
2124 uint8_t *data = NULL;
2126 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
2127 // If database read failed
2128 if (OC_STACK_OK != ret)
2130 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
2134 // Read DOXM resource from PS
2135 ret = CBORPayloadToDoxm(data, size, &gDoxm);
2138 * If SVR database in persistent storage got corrupted or
2139 * is not available for some reason, a default doxm is created
2140 * which allows user to initiate doxm provisioning again.
2142 if ((OC_STACK_OK != ret) || !data || !gDoxm)
2144 gDoxm = GetDoxmDefault();
2147 oc_mutex_lock(g_mutexDoxm);
2148 g_isDoxmNull = false;
2149 oc_mutex_unlock(g_mutexDoxm);
2151 //In case of the server is shut down unintentionally, we should initialize the owner
2152 if(gDoxm && (false == gDoxm->owned))
2154 OicUuid_t emptyUuid = {.id={0}};
2155 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
2156 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
2157 InvokeOtmEventHandler(NULL, 0, NULL, OIC_OTM_READY);
2161 ret = CheckDeviceID();
2162 if (ret == OC_STACK_OK)
2164 OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
2165 //Instantiate 'oic.sec.doxm'
2166 ret = CreateDoxmResource();
2170 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
2174 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2175 //if MOT is enabled, MOT should be prepared.
2176 if(gDoxm && gDoxm->owned)
2180 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2185 OCStackResult DeInitDoxmResource()
2187 oc_mutex_lock(g_mutexDoxm);
2188 OCStackResult ret = OCDeleteResource(gDoxmHandle);
2189 if (gDoxm != &gDefaultDoxm)
2191 DeleteDoxmBinData(gDoxm);
2194 g_isDoxmNull = true;
2196 if (OC_STACK_OK == ret)
2198 oc_mutex_unlock(g_mutexDoxm);
2203 oc_mutex_unlock(g_mutexDoxm);
2204 return OC_STACK_ERROR;
2208 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
2210 if (deviceID && gDoxm)
2212 *deviceID = gDoxm->deviceID;
2215 return OC_STACK_ERROR;
2218 OCStackResult GetDoxmIsOwned(bool *isOwned)
2220 if (isOwned && gDoxm)
2222 *isOwned = gDoxm->owned;
2225 return OC_STACK_ERROR;
2228 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
2229 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
2231 OIC_LOG_V(INFO, TAG, "In %s", __func__);
2235 return OC_STACK_INVALID_PARAM;
2237 if (MAX_UUID_SEED_SIZE < seedSize)
2239 OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
2240 return OC_STACK_INVALID_PARAM;
2242 if (MIN_UUID_SEED_SIZE > seedSize)
2244 OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
2245 return OC_STACK_INVALID_PARAM;
2248 memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
2249 memcpy(gUuidSeed, seed, seedSize);
2250 gUuidSeedSize = seedSize;
2252 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
2259 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
2261 bool isOwnerUpdated = false;
2262 bool isRownerUpdated = false;
2263 if (NULL == deviceID)
2265 return OC_STACK_INVALID_PARAM;
2269 OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
2270 return OC_STACK_NO_RESOURCE;
2273 #ifdef __WITH_DTLS__
2274 //for normal device.
2275 if (true == gDoxm->owned
2276 && memcmp(gEmptyUuid, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0
2277 && memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
2279 OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
2280 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
2281 return OC_STACK_ERROR;
2283 #endif //__WITH_DTLS
2285 //Save the previous UUID
2287 memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
2289 //Change the device UUID
2290 memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
2292 //Change the owner ID if necessary
2293 if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2295 memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
2296 isOwnerUpdated = true;
2298 //Change the resource owner ID if necessary
2299 if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2301 memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
2302 isRownerUpdated = true;
2304 // TODO: T.B.D Change resource owner for pstat, acl and cred
2307 if (!UpdatePersistentStorage(gDoxm))
2309 //revert UUID in case of PSI error
2310 memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(prevUuid.id));
2313 memcpy(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id));
2315 if (isRownerUpdated)
2317 memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id));
2319 // TODO: T.B.D Revert resource owner for pstat, acl and cred
2321 OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
2322 return OC_STACK_ERROR;
2327 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
2329 OCStackResult retVal = OC_STACK_ERROR;
2332 OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned = %d.", \
2336 *devownerid = gDoxm->owner;
2337 retVal = OC_STACK_OK;
2343 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
2345 OCStackResult retVal = OC_STACK_ERROR;
2350 *rowneruuid = gDoxm->rownerID;
2351 retVal = OC_STACK_OK;
2357 #ifdef MULTIPLE_OWNER
2359 * Compare the UUID to SubOwner.
2361 * @param[in] uuid device UUID
2363 * @return true if context->subjectId exist subowner list, else false.
2365 bool IsSubOwner(const OicUuid_t* uuid)
2367 bool retVal = false;
2374 if (gDoxm && gDoxm->subOwners)
2376 if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
2381 OicSecSubOwner_t* subOwner = NULL;
2382 LL_FOREACH(gDoxm->subOwners, subOwner)
2384 if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
2392 #endif //MULTIPLE_OWNER
2394 OCStackResult SetMOTStatus(bool enable)
2396 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2397 #ifdef MULTIPLE_OWNER
2398 OCStackResult ret = OC_STACK_NO_MEMORY;
2399 uint8_t *cborPayload = NULL;
2401 bool isDeallocateRequired = false;
2403 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
2405 if (NULL == gDoxm->mom && !enable)
2407 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2411 if (NULL == gDoxm->mom)
2413 gDoxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
2414 VERIFY_NON_NULL(TAG, gDoxm->mom, ERROR);
2415 isDeallocateRequired = true;
2418 gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
2419 gDoxm->oxmSel = OIC_PRECONFIG_PIN;
2421 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2422 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2424 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2425 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2427 isDeallocateRequired = false;
2430 if (isDeallocateRequired)
2432 OICFree(gDoxm->mom);
2436 OICFree(cborPayload);
2438 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
2442 OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2443 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2444 return OC_STACK_ERROR;
2445 #endif //MULTIPLE_OWNER
2448 OCStackResult RemoveSubOwner(const OicUuid_t* subOwner)
2450 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2451 #ifdef MULTIPLE_OWNER
2452 OCStackResult ret = OC_STACK_ERROR;
2453 bool isDeleted = false;
2455 if (NULL == subOwner)
2457 OIC_LOG(ERROR, TAG, "Invalid sub owner UUID.");
2458 return OC_STACK_INVALID_PARAM;
2462 OIC_LOG(ERROR, TAG, "Doxm resource is NULL");
2463 return OC_STACK_NO_RESOURCE;
2465 if ( NULL == gDoxm->subOwners)
2467 OIC_LOG(WARNING, TAG, "Sub Owner list is empty.");
2468 return OC_STACK_ERROR;
2471 OicSecSubOwner_t* curSubOwner = NULL;
2472 OicSecSubOwner_t* tempSubOwner = NULL;
2473 LL_FOREACH_SAFE(gDoxm->subOwners, curSubOwner, tempSubOwner)
2475 if (memcmp(curSubOwner->uuid.id, subOwner->id, sizeof(subOwner->id)) == 0 ||
2476 memcmp(WILDCARD_SUBJECT_ID.id, subOwner->id, sizeof(OicUuid_t)) == 0)
2478 char* strUuid = NULL;
2479 ret = ConvertUuidToStr(&curSubOwner->uuid, &strUuid);
2480 if (OC_STACK_OK != ret)
2482 OIC_LOG_V(ERROR, TAG, "ConvertUuidToStr error : %d", ret);
2486 OIC_LOG_V(INFO, TAG, "[%s] will be removed from sub owner list.", strUuid);
2487 LL_DELETE(gDoxm->subOwners, curSubOwner);
2489 //Remove the cred for sub owner
2490 ret = RemoveCredential(&curSubOwner->uuid);
2491 if (OC_STACK_RESOURCE_DELETED != ret)
2493 OIC_LOG_V(WARNING, TAG, "RemoveCredential error for [%s] : %d", strUuid, ret);
2497 // TODO: Remove the ACL for sub owner (Currently ACL is not required for sub-owner)
2507 //Update persistent storage
2508 if (UpdatePersistentStorage(gDoxm))
2510 ret = OC_STACK_RESOURCE_DELETED;
2514 OIC_LOG(ERROR, TAG, "UpdatePersistentStorage error");
2515 ret = OC_STACK_ERROR;
2519 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2522 OC_UNUSED(subOwner);
2523 OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2524 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2525 return OC_STACK_ERROR;
2526 #endif //MULTIPLE_OWNER
2530 OCStackResult SetNumberOfSubOwner(size_t numOfSubOwner)
2532 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2533 #ifdef MULTIPLE_OWNER
2534 if (MAX_SUBOWNER_SIZE < numOfSubOwner || MIN_SUBOWNER_SIZE > numOfSubOwner)
2536 OIC_LOG_V(ERROR, TAG, "Invalid number of sub owner : %zd", numOfSubOwner);
2537 return OC_STACK_INVALID_PARAM;
2539 gMaxSubOwnerSize = numOfSubOwner;
2540 OIC_LOG_V(DEBUG, TAG, "Number of SubOwner = %zd", gMaxSubOwnerSize);
2541 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2544 OC_UNUSED(numOfSubOwner);
2545 OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2546 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2547 return OC_STACK_ERROR;
2548 #endif //MULTIPLE_OWNER
2552 * Function to restore doxm resurce to initial status.
2553 * This function will use in case of error while ownership transfer
2555 void RestoreDoxmToInitState()
2558 gConfirmState = CONFIRM_STATE_READY;
2563 OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
2565 OicUuid_t emptyUuid = {.id={0}};
2566 memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
2567 gDoxm->owned = false;
2568 gDoxm->oxmSel = OIC_JUST_WORKS;
2570 if(!UpdatePersistentStorage(gDoxm))
2572 OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2577 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2579 OCStackResult ret = OC_STACK_ERROR;
2580 uint8_t *cborPayload = NULL;
2585 ret = OC_STACK_NO_RESOURCE;
2589 if( newROwner && (false == gDoxm->owned) )
2591 gDoxm->owned = true;
2592 memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2593 memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2595 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2596 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2598 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2599 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2601 OICFree(cborPayload);
2607 OICFree(cborPayload);