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 void * WaitConfirm(OCEntityHandlerRequest * ehRequest)
1109 bool confirmResult = false, confirmState = false;
1111 oc_mutex_lock(g_mutexWait);
1112 oc_cond_wait(g_condWait, g_mutexWait);
1113 oc_cond_free(g_condWait);
1114 oc_mutex_free(g_mutexWait);
1116 GetAsyncVerifyUserResult(&confirmResult, &confirmState);
1117 if (confirmResult == true)
1119 gConfirmState = CONFIRM_STATE_ACCEPTED;
1120 HandleDoxmPostRequest(ehRequest);
1125 gConfirmState = CONFIRM_STATE_DENIED;
1126 HandleDoxmPostRequest(ehRequest);
1131 static OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
1133 OIC_LOG(INFO, TAG, "Copying received request for slow response");
1135 if (!entityHandlerRequest)
1137 OIC_LOG_V(ERROR, TAG, "%s: entityHandlerRequest is NULL", __func__);
1141 OCEntityHandlerRequest *copyOfRequest =
1142 (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest));
1145 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1149 memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
1151 if (entityHandlerRequest->query)
1153 copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
1154 if(!copyOfRequest->query)
1156 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1157 OICFree(copyOfRequest);
1162 if (entityHandlerRequest->payload)
1164 copyOfRequest->payload =
1165 (OCSecurityPayload *)OICMalloc(sizeof(OCSecurityPayload));
1166 if(!copyOfRequest->payload)
1168 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1169 OICFree(copyOfRequest->query);
1170 OICFree(copyOfRequest);
1174 if (((OCSecurityPayload *)copyOfRequest->payload)->securityData &&
1175 ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize)
1177 ((OCSecurityPayload *)copyOfRequest->payload)->securityData =
1178 (uint8_t *)OICMalloc(((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
1179 if(!((OCSecurityPayload *)copyOfRequest->payload)->securityData)
1181 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
1182 OICFree(copyOfRequest->payload);
1183 OICFree(copyOfRequest->query);
1184 OICFree(copyOfRequest);
1188 memcpy(((OCSecurityPayload *)copyOfRequest->payload)->securityData,
1189 ((OCSecurityPayload *)entityHandlerRequest->payload)->securityData,
1190 ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
1192 ((OCSecurityPayload *)(copyOfRequest->payload))->payloadSize =
1193 ((OCSecurityPayload *)(entityHandlerRequest->payload))->payloadSize;
1195 memcpy(((OCSecurityPayload *)copyOfRequest->payload)->securityData,
1196 ((OCSecurityPayload *)entityHandlerRequest->payload)->securityData,
1197 ((OCSecurityPayload *)entityHandlerRequest->payload)->payloadSize);
1200 copyOfRequest->payload->type = entityHandlerRequest->payload->type;
1201 copyOfRequest->messageID = entityHandlerRequest->messageID;
1204 // Ignore vendor specific header options for example
1205 copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
1206 copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
1210 OIC_LOG(INFO, TAG, "Copied client request");
1214 OIC_LOG(ERROR, TAG, "Error copying client request");
1216 return copyOfRequest;
1218 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1220 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRequest)
1222 OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
1223 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1224 OicUuid_t emptyOwner = {.id = {0} };
1225 static uint16_t previousMsgId = 0;
1226 bool isDuplicatedMsg = false;
1229 * Convert CBOR Doxm data into binary. This will also validate
1230 * the Doxm data received.
1232 OicSecDoxm_t *newDoxm = NULL;
1234 if (ehRequest->payload)
1236 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1237 size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1238 bool roParsed = false;
1239 OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed);
1240 if (newDoxm && OC_STACK_OK == res)
1243 * message ID is supported for CoAP over UDP only according to RFC 7252
1244 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1245 * In case of other transport adapter, duplicate message check is not required.
1247 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1248 previousMsgId == ehRequest->messageID)
1250 isDuplicatedMsg = true;
1253 if (isDuplicatedMsg && ehRequest->messageID == gConfirmMsgId)
1255 if (CONFIRM_STATE_WAIT == gConfirmState)
1257 OIC_LOG(DEBUG, TAG, "Confirm callback already invoked.");
1258 OIC_LOG(DEBUG, TAG, "This request will be ignored.");
1259 DeleteDoxmBinData(newDoxm);
1264 OIC_LOG_V(DEBUG, TAG, "Confirm request already done, Confirm Result = %s", (CONFIRM_STATE_ACCEPTED == gConfirmState ? "ACCEPTED" : "DENIED"));
1265 ehRet = (CONFIRM_STATE_ACCEPTED == gConfirmState ? OC_EH_OK : OC_EH_NOT_ACCEPTABLE);
1270 // Check request on RO property
1271 if (true == roParsed)
1273 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only propertys");
1274 ehRet = OC_EH_NOT_ACCEPTABLE;
1278 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
1281 if (true == gDoxm->owned)
1283 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1285 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1286 ehRet = OC_EH_NOT_ACCEPTABLE;
1289 //Update gDoxm based on newDoxm
1290 updateWriteableProperty(newDoxm, gDoxm);
1292 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1293 #ifdef MULTIPLE_OWNER
1297 if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1299 CAResult_t caRes = CA_STATUS_FAILED;
1300 if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1302 caRes = CAEnableAnonECDHCipherSuite(false);
1303 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1304 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1306 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, ehRequest->devAddr.adapter);
1307 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1308 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1310 //Set the device id to derive temporal PSK
1311 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1315 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1318 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1322 //if MOM is disabled, revert the DTLS handshake callback
1323 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1325 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1330 if(newDoxm->subOwners)
1332 OicSecSubOwner_t* subowner = NULL;
1333 OicSecSubOwner_t* temp = NULL;
1335 OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1337 if(gDoxm->subOwners)
1339 LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1341 LL_DELETE(gDoxm->subOwners, subowner);
1348 LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1350 LL_DELETE(newDoxm->subOwners, subowner);
1351 LL_APPEND(gDoxm->subOwners, subowner);
1354 #endif //MULTIPLE_OWNER
1355 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1357 //Update new state in persistent storage
1358 if (UpdatePersistentStorage(gDoxm) == true)
1364 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1365 ehRet = OC_EH_ERROR;
1371 if ((false == gDoxm->owned) && (false == newDoxm->owned))
1373 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1375 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1376 ehRet = OC_EH_NOT_ACCEPTABLE;
1379 if (g_InformOxmSelectedCallback)
1381 g_InformOxmSelectedCallback(newDoxm->oxmSel);
1384 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1385 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1387 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1388 NULL, OIC_OTM_STARTED);
1392 OIC_LOG_V(INFO, TAG, "%s: request owner not empty",__func__);
1393 char* strUuid = NULL;
1394 if (OC_STACK_OK == ConvertUuidToStr(&newDoxm->owner, &strUuid))
1396 OIC_LOG_V(INFO, TAG, "%s: request owner: %s",__func__, strUuid);
1402 if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel)
1405 * If current state of the device is un-owned, enable
1406 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1407 * tool can initiate JUST_WORKS ownership transfer process.
1409 if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1411 gDoxm->oxmSel = newDoxm->oxmSel;
1412 //Update new state in persistent storage
1413 if ((UpdatePersistentStorage(gDoxm) == true))
1419 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1420 ehRet = OC_EH_ERROR;
1423 OIC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
1424 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1425 ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
1426 #endif // __WITH_DTLS__ or __WITH_TLS__
1431 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1432 //Save the owner's UUID to derive owner credential
1433 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1435 // Update new state in persistent storage
1436 if (true == UpdatePersistentStorage(gDoxm))
1442 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1443 ehRet = OC_EH_ERROR;
1448 * Disable anonymous ECDH cipher in tinyDTLS since device is now
1451 CAResult_t caRes = CA_STATUS_OK;
1452 caRes = CAEnableAnonECDHCipherSuite(false);
1453 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1454 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1456 //In case of Mutual Verified Just-Works, verify mutualVerifNum
1457 if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1458 false == isDuplicatedMsg)
1460 uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1461 uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1462 OicUuid_t deviceID = {.id = {0}};
1464 //Generate mutualVerifNum
1465 OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1467 char label[LABEL_LEN] = {0};
1468 snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1469 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1471 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1472 ehRet = OC_EH_ERROR;
1477 CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1480 gDoxm->owner.id, sizeof(gDoxm->owner.id),
1481 gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1482 preMutualVerifNum, OWNER_PSK_LENGTH_128);
1483 if (CA_STATUS_OK != pskRet)
1485 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1486 ehRet = OC_EH_ERROR;
1491 memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1492 sizeof(mutualVerifNum));
1494 gConfirmMsgId = ehRequest->messageID;
1495 gConfirmState = CONFIRM_STATE_WAIT;
1496 //Wait for user confirmation
1497 if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1499 ehRet = OC_EH_NOT_ACCEPTABLE;
1500 gConfirmState = CONFIRM_STATE_DENIED;
1505 gConfirmState = CONFIRM_STATE_ACCEPTED;
1509 #endif // __WITH_DTLS__ or __WITH_TLS__
1512 else if (OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
1515 * If current state of the device is un-owned, enable
1516 * anonymous ECDH cipher in tinyDTLS so that Provisioning
1517 * tool can initiate JUST_WORKS ownership transfer process.
1519 if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
1521 gDoxm->oxmSel = newDoxm->oxmSel;
1522 //Update new state in persistent storage
1523 if ((UpdatePersistentStorage(gDoxm) == true))
1529 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1530 ehRet = OC_EH_ERROR;
1533 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1534 CAResult_t caRes = CA_STATUS_OK;
1536 caRes = CAEnableAnonECDHCipherSuite(false);
1537 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1538 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1540 caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1541 ehRequest->devAddr.adapter);
1542 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1544 if (!isDuplicatedMsg)
1546 char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1547 if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1549 //Set the device id to derive temporal PSK
1550 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1553 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1554 * Credential should not be saved into SVR.
1555 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1557 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1558 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1563 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1564 ehRet = OC_EH_ERROR;
1567 #endif // __WITH_DTLS__ or __WITH_TLS__
1569 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1572 //Save the owner's UUID to derive owner credential
1573 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1575 // In case of random-pin based OTM, close the PIN display if callback is registered.
1576 if (!isDuplicatedMsg)
1581 //Update new state in persistent storage
1582 if (UpdatePersistentStorage(gDoxm) == true)
1588 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1589 ehRet = OC_EH_ERROR;
1592 #endif // __WITH_DTLS__ or __WITH_TLS__
1594 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1595 else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel)
1597 if (CONFIRM_STATE_ACCEPTED != gConfirmState && CONFIRM_STATE_DENIED != gConfirmState)
1599 //Get user confirmation
1600 if (false == newDoxm->owned &&
1601 false == isDuplicatedMsg &&
1602 memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0)
1604 gConfirmMsgId = ehRequest->messageID;
1605 gConfirmState = CONFIRM_STATE_WAIT;
1607 if (OC_STACK_OK != VerifyUserConfirm())
1609 if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1611 ehRet = OC_EH_NOT_ACCEPTABLE;
1612 gConfirmState = CONFIRM_STATE_DENIED;
1618 OCEntityHandlerRequest * ehRequestCopy = CopyRequest(ehRequest);
1619 VERIFY_NON_NULL(TAG, ehRequestCopy, ERROR);
1621 g_condWait = oc_cond_new();
1622 g_mutexWait = oc_mutex_new();
1623 if (oc_thread_new (&g_waitConfirmThreadId, WaitConfirm, ehRequestCopy))
1625 oc_thread_detach(g_waitConfirmThreadId);
1631 else if (CONFIRM_STATE_DENIED == gConfirmState)
1633 ehRet = OC_EH_NOT_ACCEPTABLE;
1637 //Save the owner's UUID to derive owner credential
1638 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1639 gDoxm->oxmSel = newDoxm->oxmSel;
1640 //Update new state in persistent storage
1641 if (UpdatePersistentStorage(gDoxm))
1647 OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
1648 ehRet = OC_EH_ERROR;
1650 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1651 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1652 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
1654 //Unset pre-selected ciphersuite, if any
1655 caRes = CASelectCipherSuite(0, ehRequest->devAddr.adapter);
1656 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1657 OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
1659 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1660 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
1662 #endif // __WITH_DTLS__ or __WITH_TLS__
1666 * When current state of the device is un-owned and Provisioning
1667 * Tool is attempting to change the state to 'Owned' with a
1668 * qualified value for the field 'Owner'
1670 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1671 (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
1673 //Change the SVR's resource owner as owner device.
1674 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1675 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1677 ehRet = OC_EH_ERROR;
1680 ownerRes = SetAmaclRownerId(&gDoxm->owner);
1681 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1683 ehRet = OC_EH_ERROR;
1686 ownerRes = SetCredRownerId(&gDoxm->owner);
1687 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1689 ehRet = OC_EH_ERROR;
1692 ownerRes = SetPstatRownerId(&gDoxm->owner);
1693 if(OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1695 ehRet = OC_EH_ERROR;
1699 gDoxm->owned = true;
1700 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1702 // Update new state in persistent storage
1703 if (UpdatePersistentStorage(gDoxm))
1705 //Update default ACE of security resource to prevent anonymous user access.
1706 if(OC_STACK_OK == UpdateDefaultSecProvACE())
1712 OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
1713 ehRet = OC_EH_ERROR;
1718 OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
1719 ehRet = OC_EH_ERROR;
1721 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1722 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1723 OIC_CON_MFG_CERT== gDoxm->oxmSel)
1725 CAregisterPkixInfoHandler(GetPkixInfo);
1726 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1729 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1730 &gDoxm->owner, OIC_OTM_DONE);
1731 #endif // __WITH_DTLS__ or __WITH_TLS__
1737 if(OC_EH_OK != ehRet)
1740 * If some error is occured while ownership transfer,
1741 * ownership transfer related resource should be revert back to initial status.
1747 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1749 if (!isDuplicatedMsg)
1751 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1752 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
1753 NULL, OIC_OTM_ERROR);
1755 RestoreDoxmToInitState();
1756 RestorePstatToInitState();
1757 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1763 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1767 previousMsgId = ehRequest->messageID;
1769 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
1770 CAEndpoint_t peer = {0};
1771 OCDevAddr devAddr = ehRequest->devAddr;
1773 memcpy(&peer.addr, &devAddr.addr, sizeof(peer.addr));
1774 peer.port = devAddr.port;
1775 peer.adapter = (CATransportAdapter_t)devAddr.adapter;
1777 if ((devAddr.flags & OC_FLAG_SECURE) && (false == CAIsExistSslPeer(&peer)))
1779 OIC_LOG_V(WARNING, TAG, "Not Exist Peer");
1784 //Send payload to request originator
1785 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1786 OC_EH_OK : OC_EH_ERROR;
1789 //Send payload to request originator
1790 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1791 OC_EH_OK : OC_EH_ERROR;
1794 DeleteDoxmBinData(newDoxm);
1799 #ifdef MULTIPLE_OWNER
1800 static OCEntityHandlerResult HandleDoxmDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1802 OIC_LOG(DEBUG, TAG, "Processing DoxmDeleteRequest");
1804 OCEntityHandlerResult ehRet = OC_EH_BAD_REQ;
1806 if (NULL == ehRequest->query)
1811 OicParseQueryIter_t parseIter = { .attrPos=NULL };
1812 OicUuid_t subject = {.id={0}};
1814 //Parsing REST query to get the subject
1815 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1816 while (GetNextQuery(&parseIter))
1818 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBOWNERID_NAME,
1819 parseIter.attrLen) == 0)
1821 if (0 == strncmp((const char*)parseIter.valPos, WILDCARD_RESOURCE_URI,
1822 strlen(WILDCARD_RESOURCE_URI)))
1824 if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&WILDCARD_SUBJECT_ID))
1826 ehRet = OC_EH_RESOURCE_DELETED;
1831 OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1832 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1834 if(OC_STACK_RESOURCE_DELETED == RemoveSubOwner(&subject))
1836 ehRet = OC_EH_RESOURCE_DELETED;
1842 //Send response to request originator
1843 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1844 OC_EH_OK : OC_EH_ERROR;
1850 #endif //MULTIPLE_OWNER
1852 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1853 OCEntityHandlerRequest * ehRequest,
1854 void* callbackParam)
1856 (void)callbackParam;
1857 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1859 if(NULL == ehRequest)
1864 oc_mutex_lock(g_mutexDoxm);
1868 oc_mutex_unlock(g_mutexDoxm);
1869 return OC_EH_SERVICE_UNAVAILABLE;
1872 if (flag & OC_REQUEST_FLAG)
1874 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1876 switch (ehRequest->method)
1879 ehRet = HandleDoxmGetRequest(ehRequest);
1883 ehRet = HandleDoxmPostRequest(ehRequest);
1886 #ifdef MULTIPLE_OWNER
1887 case OC_REST_DELETE:
1888 ehRet = HandleDoxmDeleteRequest(ehRequest);
1890 #endif //MULTIPLE_OWNER
1893 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1894 OC_EH_OK : OC_EH_ERROR;
1898 oc_mutex_unlock(g_mutexDoxm);
1904 OCStackResult CreateDoxmResource()
1906 OCStackResult ret = OCCreateResource(&gDoxmHandle,
1907 OIC_RSRC_TYPE_SEC_DOXM,
1908 OC_RSRVD_INTERFACE_DEFAULT,
1915 if (OC_STACK_OK != ret)
1917 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1918 DeInitDoxmResource();
1924 * Checks if DeviceID is generated during provisioning for the new device.
1925 * If DeviceID is NULL then generates the new DeviceID.
1926 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1928 static OCStackResult CheckDeviceID()
1930 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1932 OCStackResult ret = OC_STACK_ERROR;
1933 bool validId = false;
1937 OIC_LOG_V(ERROR, TAG, "%s: gDoxm is NULL", __func__);
1938 return OC_STACK_INVALID_PARAM;
1941 for (uint8_t i = 0; i < UUID_LENGTH; i++)
1943 if (gDoxm->deviceID.id[i] != 0)
1952 char* strUuid = NULL;
1953 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1954 //If seed value is exist, generate UUID using seed with SHA256
1955 if (0 != gUuidSeedSize)
1957 uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1958 mbedtls_md_context_t sha_ctx;
1961 OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1962 OIC_LOG(DEBUG, TAG, "Seed value : ");
1963 OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1965 mbedtls_md_init( &sha_ctx );
1966 mbedret = mbedtls_md_setup( &sha_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 );
1969 mbedtls_md_starts( &sha_ctx );
1970 mbedtls_md_update( &sha_ctx, gUuidSeed, gUuidSeedSize);
1971 mbedtls_md_finish(&sha_ctx, (unsigned char*)hashVal);
1972 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1977 OIC_LOG_V(ERROR, TAG, "mbedtls_md_setup() returned -0x%04x\n", -mbedret);
1978 ret = OC_STACK_ERROR;
1980 mbedtls_md_free( &sha_ctx );
1984 if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
1986 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1987 return OC_STACK_ERROR;
1992 if (RAND_UUID_OK != OCGenerateUuid(gDoxm->deviceID.id))
1994 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
2000 if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
2002 OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
2007 OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
2011 if (!UpdatePersistentStorage(gDoxm))
2013 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
2014 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
2022 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
2028 * Get the default value.
2030 * @return the default value of doxm, @ref OicSecDoxm_t.
2032 static OicSecDoxm_t* GetDoxmDefault()
2034 OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
2035 return &gDefaultDoxm;
2038 const OicSecDoxm_t* GetDoxmResourceData()
2043 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2045 * Internal API to prepare MOT
2047 static void PrepareMOT(const OicSecDoxm_t* doxm)
2049 OIC_LOG(INFO, TAG, "IN PrepareMOT");
2050 VERIFY_NON_NULL(TAG, doxm, ERROR);
2052 if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
2054 CAResult_t caRes = CA_STATUS_FAILED;
2056 OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
2058 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
2060 caRes = CAEnableAnonECDHCipherSuite(false);
2061 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
2062 OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
2064 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
2065 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
2067 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
2068 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
2070 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
2072 //Set the device id to derive temporal PSK
2073 SetUuidForPinBasedOxm(&doxm->deviceID);
2077 OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
2081 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
2084 OIC_LOG(INFO, TAG, "OUT PrepareMOT");
2087 OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
2089 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2091 OCStackResult InitDoxmResource()
2093 OCStackResult ret = OC_STACK_ERROR;
2097 g_mutexDoxm = oc_mutex_new();
2100 return OC_STACK_ERROR;
2104 gConfirmState = CONFIRM_STATE_READY;
2107 //Read DOXM resource from PS
2108 uint8_t *data = NULL;
2110 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
2111 // If database read failed
2112 if (OC_STACK_OK != ret)
2114 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
2118 // Read DOXM resource from PS
2119 ret = CBORPayloadToDoxm(data, size, &gDoxm);
2122 * If SVR database in persistent storage got corrupted or
2123 * is not available for some reason, a default doxm is created
2124 * which allows user to initiate doxm provisioning again.
2126 if ((OC_STACK_OK != ret) || !data || !gDoxm)
2128 gDoxm = GetDoxmDefault();
2131 oc_mutex_lock(g_mutexDoxm);
2132 g_isDoxmNull = false;
2133 oc_mutex_unlock(g_mutexDoxm);
2135 //In case of the server is shut down unintentionally, we should initialize the owner
2136 if(gDoxm && (false == gDoxm->owned))
2138 OicUuid_t emptyUuid = {.id={0}};
2139 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
2140 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
2141 InvokeOtmEventHandler(NULL, 0, NULL, OIC_OTM_READY);
2145 ret = CheckDeviceID();
2146 if (ret == OC_STACK_OK)
2148 OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
2149 //Instantiate 'oic.sec.doxm'
2150 ret = CreateDoxmResource();
2154 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
2158 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2159 //if MOT is enabled, MOT should be prepared.
2160 if(gDoxm && gDoxm->owned)
2164 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2169 OCStackResult DeInitDoxmResource()
2171 oc_mutex_lock(g_mutexDoxm);
2172 OCStackResult ret = OCDeleteResource(gDoxmHandle);
2173 if (gDoxm != &gDefaultDoxm)
2175 DeleteDoxmBinData(gDoxm);
2178 g_isDoxmNull = true;
2180 if (OC_STACK_OK == ret)
2182 oc_mutex_unlock(g_mutexDoxm);
2187 oc_mutex_unlock(g_mutexDoxm);
2188 return OC_STACK_ERROR;
2192 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
2194 if (deviceID && gDoxm)
2196 *deviceID = gDoxm->deviceID;
2199 return OC_STACK_ERROR;
2202 OCStackResult GetDoxmIsOwned(bool *isOwned)
2204 if (isOwned && gDoxm)
2206 *isOwned = gDoxm->owned;
2209 return OC_STACK_ERROR;
2212 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
2213 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
2215 OIC_LOG_V(INFO, TAG, "In %s", __func__);
2219 return OC_STACK_INVALID_PARAM;
2221 if (MAX_UUID_SEED_SIZE < seedSize)
2223 OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
2224 return OC_STACK_INVALID_PARAM;
2226 if (MIN_UUID_SEED_SIZE > seedSize)
2228 OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
2229 return OC_STACK_INVALID_PARAM;
2232 memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
2233 memcpy(gUuidSeed, seed, seedSize);
2234 gUuidSeedSize = seedSize;
2236 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
2243 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceID)
2245 bool isOwnerUpdated = false;
2246 bool isRownerUpdated = false;
2247 if (NULL == deviceID)
2249 return OC_STACK_INVALID_PARAM;
2253 OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
2254 return OC_STACK_NO_RESOURCE;
2257 #ifdef __WITH_DTLS__
2258 //for normal device.
2259 if (true == gDoxm->owned
2260 && memcmp(gEmptyUuid, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0
2261 && memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
2263 OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
2264 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
2265 return OC_STACK_ERROR;
2267 #endif //__WITH_DTLS
2269 //Save the previous UUID
2271 memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
2273 //Change the device UUID
2274 memcpy(gDoxm->deviceID.id, deviceID->id, sizeof(deviceID->id));
2276 //Change the owner ID if necessary
2277 if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2279 memcpy(gDoxm->owner.id, deviceID->id, sizeof(deviceID->id));
2280 isOwnerUpdated = true;
2282 //Change the resource owner ID if necessary
2283 if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2285 memcpy(gDoxm->rownerID.id, deviceID->id, sizeof(deviceID->id));
2286 isRownerUpdated = true;
2288 // TODO: T.B.D Change resource owner for pstat, acl and cred
2291 if (!UpdatePersistentStorage(gDoxm))
2293 //revert UUID in case of PSI error
2294 memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(prevUuid.id));
2297 memcpy(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id));
2299 if (isRownerUpdated)
2301 memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id));
2303 // TODO: T.B.D Revert resource owner for pstat, acl and cred
2305 OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
2306 return OC_STACK_ERROR;
2311 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devownerid)
2313 OCStackResult retVal = OC_STACK_ERROR;
2316 OIC_LOG_V(DEBUG, TAG, "GetDoxmDevOwnerId(): gDoxm owned = %d.", \
2320 *devownerid = gDoxm->owner;
2321 retVal = OC_STACK_OK;
2327 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
2329 OCStackResult retVal = OC_STACK_ERROR;
2334 *rowneruuid = gDoxm->rownerID;
2335 retVal = OC_STACK_OK;
2341 #ifdef MULTIPLE_OWNER
2343 * Compare the UUID to SubOwner.
2345 * @param[in] uuid device UUID
2347 * @return true if context->subjectId exist subowner list, else false.
2349 bool IsSubOwner(const OicUuid_t* uuid)
2351 bool retVal = false;
2358 if (gDoxm && gDoxm->subOwners)
2360 if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
2365 OicSecSubOwner_t* subOwner = NULL;
2366 LL_FOREACH(gDoxm->subOwners, subOwner)
2368 if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
2376 #endif //MULTIPLE_OWNER
2378 OCStackResult SetMOTStatus(bool enable)
2380 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2381 #ifdef MULTIPLE_OWNER
2382 OCStackResult ret = OC_STACK_NO_MEMORY;
2383 uint8_t *cborPayload = NULL;
2385 bool isDeallocateRequired = false;
2387 VERIFY_NON_NULL(TAG, gDoxm, ERROR);
2389 if (NULL == gDoxm->mom && !enable)
2391 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2395 if (NULL == gDoxm->mom)
2397 gDoxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
2398 VERIFY_NON_NULL(TAG, gDoxm->mom, ERROR);
2399 isDeallocateRequired = true;
2402 gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
2403 gDoxm->oxmSel = OIC_PRECONFIG_PIN;
2405 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2406 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2408 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2409 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2411 isDeallocateRequired = false;
2414 if (isDeallocateRequired)
2416 OICFree(gDoxm->mom);
2420 OICFree(cborPayload);
2422 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
2426 OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2427 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2428 return OC_STACK_ERROR;
2429 #endif //MULTIPLE_OWNER
2432 OCStackResult RemoveSubOwner(const OicUuid_t* subOwner)
2434 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2435 #ifdef MULTIPLE_OWNER
2436 OCStackResult ret = OC_STACK_ERROR;
2437 bool isDeleted = false;
2439 if (NULL == subOwner)
2441 OIC_LOG(ERROR, TAG, "Invalid sub owner UUID.");
2442 return OC_STACK_INVALID_PARAM;
2446 OIC_LOG(ERROR, TAG, "Doxm resource is NULL");
2447 return OC_STACK_NO_RESOURCE;
2449 if ( NULL == gDoxm->subOwners)
2451 OIC_LOG(WARNING, TAG, "Sub Owner list is empty.");
2452 return OC_STACK_ERROR;
2455 OicSecSubOwner_t* curSubOwner = NULL;
2456 OicSecSubOwner_t* tempSubOwner = NULL;
2457 LL_FOREACH_SAFE(gDoxm->subOwners, curSubOwner, tempSubOwner)
2459 if (memcmp(curSubOwner->uuid.id, subOwner->id, sizeof(subOwner->id)) == 0 ||
2460 memcmp(WILDCARD_SUBJECT_ID.id, subOwner->id, sizeof(OicUuid_t)) == 0)
2462 char* strUuid = NULL;
2463 ret = ConvertUuidToStr(&curSubOwner->uuid, &strUuid);
2464 if (OC_STACK_OK != ret)
2466 OIC_LOG_V(ERROR, TAG, "ConvertUuidToStr error : %d", ret);
2470 OIC_LOG_V(INFO, TAG, "[%s] will be removed from sub owner list.", strUuid);
2471 LL_DELETE(gDoxm->subOwners, curSubOwner);
2473 //Remove the cred for sub owner
2474 ret = RemoveCredential(&curSubOwner->uuid);
2475 if (OC_STACK_RESOURCE_DELETED != ret)
2477 OIC_LOG_V(WARNING, TAG, "RemoveCredential error for [%s] : %d", strUuid, ret);
2481 // TODO: Remove the ACL for sub owner (Currently ACL is not required for sub-owner)
2491 //Update persistent storage
2492 if (UpdatePersistentStorage(gDoxm))
2494 ret = OC_STACK_RESOURCE_DELETED;
2498 OIC_LOG(ERROR, TAG, "UpdatePersistentStorage error");
2499 ret = OC_STACK_ERROR;
2503 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2506 OC_UNUSED(subOwner);
2507 OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2508 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2509 return OC_STACK_ERROR;
2510 #endif //MULTIPLE_OWNER
2514 OCStackResult SetNumberOfSubOwner(size_t numOfSubOwner)
2516 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2517 #ifdef MULTIPLE_OWNER
2518 if (MAX_SUBOWNER_SIZE < numOfSubOwner || MIN_SUBOWNER_SIZE > numOfSubOwner)
2520 OIC_LOG_V(ERROR, TAG, "Invalid number of sub owner : %zd", numOfSubOwner);
2521 return OC_STACK_INVALID_PARAM;
2523 gMaxSubOwnerSize = numOfSubOwner;
2524 OIC_LOG_V(DEBUG, TAG, "Number of SubOwner = %zd", gMaxSubOwnerSize);
2525 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2528 OC_UNUSED(numOfSubOwner);
2529 OIC_LOG(DEBUG, TAG, "Multiple Owner is not enabled.");
2530 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2531 return OC_STACK_ERROR;
2532 #endif //MULTIPLE_OWNER
2536 * Function to restore doxm resurce to initial status.
2537 * This function will use in case of error while ownership transfer
2539 void RestoreDoxmToInitState()
2542 gConfirmState = CONFIRM_STATE_READY;
2547 OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
2549 OicUuid_t emptyUuid = {.id={0}};
2550 memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
2551 gDoxm->owned = false;
2552 gDoxm->oxmSel = OIC_JUST_WORKS;
2554 if(!UpdatePersistentStorage(gDoxm))
2556 OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2561 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2563 OCStackResult ret = OC_STACK_ERROR;
2564 uint8_t *cborPayload = NULL;
2569 ret = OC_STACK_NO_RESOURCE;
2573 if( newROwner && (false == gDoxm->owned) )
2575 gDoxm->owned = true;
2576 memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2577 memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2579 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size, false);
2580 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2582 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2583 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2585 OICFree(cborPayload);
2591 OICFree(cborPayload);