1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include "iotivity_config.h"
21 #include "iotivity_debug.h"
30 #include "oic_malloc.h"
31 #include "payload_logging.h"
34 #include "ocpayload.h"
35 #include "ocpayloadcbor.h"
36 #include "cainterface.h"
37 #include "ocserverrequest.h"
38 #include "resourcemanager.h"
39 #include "doxmresource.h"
40 #include "pstatresource.h"
41 #include "deviceonboardingstate.h"
42 #include "aclresource.h"
43 #include "amaclresource.h"
44 #include "pconfresource.h"
45 #include "dpairingresource.h"
46 #include "psinterface.h"
47 #include "srmresourcestrings.h"
48 #include "credresource.h"
49 #include "srmutility.h"
50 #include "pinoxmcommon.h"
51 #include "oxmverifycommon.h"
52 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
53 #include <mbedtls/ssl_ciphersuites.h>
54 #include <mbedtls/md.h>
55 #include "pkix_interface.h"
58 #define TAG "OIC_SRM_DOXM"
59 #define CHAR_ZERO ('0')
61 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
62 * The value of payload size is increased until reaching belox max cbor size. */
63 static const uint16_t CBOR_SIZE = 512;
65 /** Max cbor size payload. */
66 static const uint16_t CBOR_MAX_SIZE = 4400;
68 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
69 /** MAX uuid seed size */
70 #define MAX_UUID_SEED_SIZE (64)
71 /** MIN uuid seed size */
72 #define MIN_UUID_SEED_SIZE (8)
74 /** Buffer to save the seed of device UUID */
75 static uint8_t gUuidSeed[MAX_UUID_SEED_SIZE];
76 static size_t gUuidSeedSize = 0;
79 static OicSecDoxm_t *gDoxm = NULL;
80 static OCResourceHandle gDoxmHandle = NULL;
82 static OicSecOxm_t gDoxmDefaultOxm = OIC_RANDOM_DEVICE_PIN;
83 static OicSecDoxm_t gDefaultDoxm =
85 &gDoxmDefaultOxm, /* uint16_t *oxm */
86 1, /* size_t oxmLen */
87 OIC_RANDOM_DEVICE_PIN, /* uint16_t oxmSel */
88 SYMMETRIC_PAIR_WISE_KEY | SIGNED_ASYMMETRIC_KEY, /* OicSecCredType_t sct */
89 false, /* bool owned */
90 {.id = {0}}, /* OicUuid_t deviceID */
92 {.id = {0}}, /* OicUuid_t owner */
94 NULL, /* OicSecSubOwner_t sub-owner list */
95 NULL, /* OicSecMomType_t multiple owner mode */
96 #endif //MULTIPLE_OWNER
97 {.id = {0}}, /* OicUuid_t rownerID */
100 #define R PERMISSION_READ
101 #define W PERMISSION_WRITE
102 #define RW PERMISSION_READ | PERMISSION_WRITE
104 // NOTE that this table must match the DoxmProperty_t enum in doxmresource.h
105 static const uint8_t gDoxmPropertyAccessModes[DOXM_PROPERTY_COUNT][DOS_STATE_COUNT] =
106 { // RESET RFOTM RFPRO RFNOP SRESET
107 { R, R, R, R, R }, // .oxmtype TODO [IOT-2105]
108 { R, R, R, R, R }, // .oxms
109 #ifdef MULTIPLE_OWNER
110 { R, RW, RW, R, R }, // .oxmsel
112 { R, RW, R, R, R }, // .oxmsel
113 #endif // MULTIPLE_OWNER
114 { R, R, R, R, R }, // .sct
115 { R, RW, R, R, R }, // .owned
116 #ifdef MULTIPLE_OWNER
117 { RW, RW, RW, RW, RW }, // .subowner
118 { RW, RW, RW, RW, RW }, // .mom
119 #endif // MULTIPLE_OWNER
120 { R, RW, R, R, R }, // .deviceuuid
121 { R, RW, R, R, R }, // .devowneruuid
122 { R, RW, R, R, RW } // .rowneruuid
129 static bool IsPropertyReadOnly(DoxmProperty_t p,
130 OicSecDeviceOnboardingState_t s)
134 if (PERMISSION_READ == gDoxmPropertyAccessModes[p][s])
136 OIC_LOG_V(DEBUG, TAG, "%s: property %d is read-only in state %d.",
145 * Internal method converts CBOR into DOXM data, and determines if a read-only
146 * Property was parsed in the CBOR payload.
148 * @param[in] cborPayload The doxm data in cbor format.
149 * @param[in] size Size of the cborPayload. In case 0 is provided it assigns CBOR_SIZE (255) value.
150 * @param[out] doxm Pointer to @ref OicSecDoxm_t.
151 * @param[out] roParsed Ptr to bool marked "true" iff a read-only Property is parsed
152 * @param[in] stateForReadOnlyCheck The state to use when determining if a Property is
155 * @return ::OC_STACK_OK for Success, otherwise some error value.
157 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
158 OicSecDoxm_t **doxm, bool *roParsed,
159 OicSecDeviceOnboardingState_t stateForReadOnlyCheck);
161 void DeleteDoxmBinData(OicSecDoxm_t* doxm)
168 #ifdef MULTIPLE_OWNER
172 //clean sub-owner list
173 if(NULL != doxm->subOwners)
175 OicSecSubOwner_t* subowner = NULL;
176 OicSecSubOwner_t* temp = NULL;
177 LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
179 LL_DELETE(doxm->subOwners, subowner);
183 #endif //MULTIPLE_OWNER
190 OCStackResult DoxmToCBORPayloadPartial(const OicSecDoxm_t *doxm,
191 uint8_t **payload, size_t *size, const bool *propertiesToInclude)
193 if (NULL == doxm || NULL == payload || NULL != *payload || NULL == size)
195 return OC_STACK_INVALID_PARAM;
197 size_t cborLen = *size;
205 OCStackResult ret = OC_STACK_ERROR;
209 char* strUuid = NULL;
211 int64_t cborEncoderResult = CborNoError;
213 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
214 VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
216 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
218 cborEncoderResult = cbor_encoder_create_map(&encoder, &doxmMap, CborIndefiniteLength);
219 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Map.");
222 if (propertiesToInclude[DOXM_OXMS] && doxm->oxmLen > 0)
224 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_OXMS_NAME);
226 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXMS_NAME,
227 strlen(OIC_JSON_OXMS_NAME));
228 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxms Tag.");
229 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &oxm, doxm->oxmLen);
230 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxms Array.");
232 for (size_t i = 0; i < doxm->oxmLen; i++)
234 cborEncoderResult = cbor_encode_int(&oxm, doxm->oxm[i]);
235 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxms Value");
237 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &oxm);
238 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing oxms.");
242 if (propertiesToInclude[DOXM_OXMSEL] && doxm->oxmLen > 0)
244 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_OXM_SEL_NAME);
245 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_OXM_SEL_NAME,
246 strlen(OIC_JSON_OXM_SEL_NAME));
247 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmsel Tag.");
248 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->oxmSel);
249 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding oxmsel Value.");
253 if (propertiesToInclude[DOXM_SCT])
255 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_SUPPORTED_CRED_TYPE_NAME);
256 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUPPORTED_CRED_TYPE_NAME,
257 strlen(OIC_JSON_SUPPORTED_CRED_TYPE_NAME));
258 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding sct Tag");
259 cborEncoderResult = cbor_encode_int(&doxmMap, doxm->sct);
260 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding sct Value.");
264 if (propertiesToInclude[DOXM_OWNED])
266 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_OWNED_NAME);
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.");
274 // deviceuuid Property
275 if (propertiesToInclude[DOXM_DEVICEUUID])
277 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_DEVICE_ID_NAME);
278 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVICE_ID_NAME,
279 strlen(OIC_JSON_DEVICE_ID_NAME));
280 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding deviceuuid Tag.");
281 ret = ConvertUuidToStr(&doxm->deviceID, &strUuid);
282 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
283 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
284 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding deviceuuid Value.");
289 #ifdef MULTIPLE_OWNER
290 //Device SubOwnerID -- Not Mandatory
291 if(propertiesToInclude[DOXM_SUBOWNER] && doxm->subOwners)
293 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_SUBOWNERID_NAME);
294 size_t subOwnerLen = 0;
295 OicSecSubOwner_t* subOwner = NULL;
296 LL_FOREACH(doxm->subOwners, subOwner)
301 CborEncoder subOwners;
302 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
303 strlen(OIC_JSON_SUBOWNERID_NAME));
304 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
305 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
306 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
309 LL_FOREACH(doxm->subOwners, subOwner)
311 char* strSubOwnerUuid = NULL;
312 ret = ConvertUuidToStr(&subOwner->uuid, &strSubOwnerUuid);
313 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
314 cborEncoderResult = cbor_encode_text_string(&subOwners, strSubOwnerUuid, strlen(strSubOwnerUuid));
315 OICFree(strSubOwnerUuid);
316 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
318 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
319 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
322 //Multiple Owner Mode -- Not Mandatory
323 if(propertiesToInclude[DOXM_MOM] && doxm->mom)
325 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_MOM_NAME);
326 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
327 strlen(OIC_JSON_MOM_NAME));
328 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
329 cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
330 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
332 #endif //MULTIPLE_OWNER
334 // devowneruuid Property
335 if (propertiesToInclude[DOXM_DEVOWNERUUID])
337 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_DEVOWNERID_NAME);
338 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
339 strlen(OIC_JSON_DEVOWNERID_NAME));
340 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding devowneruuid Tag.");
341 ret = ConvertUuidToStr(&doxm->owner, &strUuid);
342 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
343 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
344 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding devowneruuid Value.");
349 // rowneruuid Property
350 if (propertiesToInclude[DOXM_ROWNERUUID])
352 OIC_LOG_V(DEBUG, TAG, "%s: including %s Property.", __func__, OIC_JSON_ROWNERID_NAME);
353 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_ROWNERID_NAME,
354 strlen(OIC_JSON_ROWNERID_NAME));
355 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rowneruuid Tag.");
356 ret = ConvertUuidToStr(&doxm->rownerID, &strUuid);
357 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
358 cborEncoderResult = cbor_encode_text_string(&doxmMap, strUuid, strlen(strUuid));
359 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rowneruuid Value.");
366 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_RT_NAME,
367 strlen(OIC_JSON_RT_NAME));
368 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
369 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &rtArray, 1);
370 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
371 for (size_t i = 0; i < 1; i++)
373 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_DOXM,
374 strlen(OIC_RSRC_TYPE_SEC_DOXM));
375 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
377 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &rtArray);
378 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
382 cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_IF_NAME,
383 strlen(OIC_JSON_IF_NAME));
384 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
385 cborEncoderResult = cbor_encoder_create_array(&doxmMap, &ifArray, 1);
386 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
387 for (size_t i = 0; i < 1; i++)
389 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
390 strlen(OC_RSRVD_INTERFACE_DEFAULT));
391 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
393 cborEncoderResult = cbor_encoder_close_container(&doxmMap, &ifArray);
394 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
396 cborEncoderResult = cbor_encoder_close_container(&encoder, &doxmMap);
397 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing DoxmMap.");
399 if (CborNoError == cborEncoderResult)
401 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
402 *payload = outPayload;
406 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
408 OIC_LOG(DEBUG, TAG, "Memory getting reallocated.");
409 // reallocate and try again!
412 // Since the allocated initial memory failed, double the memory.
413 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
414 OIC_LOG_V(DEBUG, TAG, "Doxm reallocation size : %zd.", cborLen);
415 cborEncoderResult = CborNoError;
416 ret = DoxmToCBORPayloadPartial(doxm, payload, &cborLen, propertiesToInclude);
420 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
426 ret = OC_STACK_ERROR;
432 OCStackResult DoxmToCBORPayload(const OicSecDoxm_t *doxm,
433 uint8_t **payload, size_t *size)
435 bool allProps[DOXM_PROPERTY_COUNT];
437 for (int i = 0; i < DOXM_PROPERTY_COUNT; i++)
442 return DoxmToCBORPayloadPartial(doxm, payload, size, allProps);
445 OCStackResult CBORPayloadToDoxm(const uint8_t *cborPayload, size_t size,
446 OicSecDoxm_t **secDoxm)
448 return CBORPayloadToDoxmBin(cborPayload, size, secDoxm, NULL, DOS_RESET);
451 static OCStackResult CBORPayloadToDoxmBin(const uint8_t *cborPayload, size_t size,
452 OicSecDoxm_t **secDoxm, bool *roParsed,
453 OicSecDeviceOnboardingState_t stateForReadOnlyCheck)
455 if (NULL == cborPayload || NULL == secDoxm || NULL != *secDoxm || 0 == size)
457 return OC_STACK_INVALID_PARAM;
460 OCStackResult ret = OC_STACK_ERROR;
464 CborError cborFindResult = CborNoError;
465 char* strUuid = NULL;
469 cbor_parser_init(cborPayload, size, 0, &parser, &doxmCbor);
471 OicSecDoxm_t *doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(*doxm));
472 VERIFY_NOT_NULL(TAG, doxm, ERROR);
474 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXMS_NAME, &doxmMap);
477 if (CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
479 OIC_LOG(DEBUG, TAG, "Found doxm.oxms tag in doxmMap.");
481 cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
482 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxms array Length.");
483 VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
485 doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
486 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
488 cborFindResult = cbor_value_enter_container(&doxmMap, &oxm);
489 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering oxms 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 oxms Value")
498 OIC_LOG_V(DEBUG, TAG, "Read doxm.oxms value = %d", tmp);
499 doxm->oxm[i++] = (OicSecOxm_t)tmp;
500 cborFindResult = cbor_value_advance(&oxm);
501 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxms.")
506 if (IsPropertyReadOnly(DOXM_OXMS, stateForReadOnlyCheck))
514 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
515 doxm->oxm = (OicSecOxm_t *) OICCalloc(gDoxm->oxmLen, sizeof(*doxm->oxm));
516 VERIFY_NOT_NULL(TAG, doxm->oxm, ERROR);
517 doxm->oxmLen = gDoxm->oxmLen;
518 for (size_t i = 0; i < gDoxm->oxmLen; i++)
520 doxm->oxm[i] = gDoxm->oxm[i];
525 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OXM_SEL_NAME, &doxmMap);
526 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
528 OIC_LOG(DEBUG, TAG, "Found doxm.oxmsel tag in doxmMap.");
532 cborFindResult = cbor_value_get_int(&doxmMap, &oxmSel);
533 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sel Name Value.")
534 OIC_LOG_V(DEBUG, TAG, "Read doxm.oxmsel value = %d", oxmSel);
535 doxm->oxmSel = (OicSecOxm_t)oxmSel;
538 if (IsPropertyReadOnly(DOXM_OXMSEL, stateForReadOnlyCheck))
544 else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
546 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
547 doxm->oxmSel = gDoxm->oxmSel;
551 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, &doxmMap);
552 if (CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
554 OIC_LOG(DEBUG, TAG, "Found doxm.oxmsel tag in doxmMap.");
557 cborFindResult = cbor_value_get_int(&doxmMap, &sct);
558 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Sct Name Value.")
559 OIC_LOG_V(DEBUG, TAG, "Read doxm.sct value = %d", sct);
560 doxm->sct = (OicSecCredType_t)sct;
564 if (IsPropertyReadOnly(DOXM_SCT, stateForReadOnlyCheck))
570 else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
572 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
573 doxm->sct = gDoxm->sct;
577 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_OWNED_NAME, &doxmMap);
578 if (CborNoError == cborFindResult && cbor_value_is_boolean(&doxmMap))
580 OIC_LOG(DEBUG, TAG, "Found doxm.owned tag in doxmMap.");
581 cborFindResult = cbor_value_get_boolean(&doxmMap, &doxm->owned);
582 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owned Value.")
583 OIC_LOG_V(DEBUG, TAG, "Read doxm.owned value = %s", doxm->owned?"true":"false");
587 if (IsPropertyReadOnly(DOXM_OWNED, stateForReadOnlyCheck))
593 else // PUT/POST JSON may not have owned so set it to the gDomx->owned
595 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
596 doxm->owned = gDoxm->owned;
600 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVICE_ID_NAME, &doxmMap);
601 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
603 OIC_LOG(DEBUG, TAG, "Found doxm.deviceuuid tag in doxmMap.");
604 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
605 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
606 OIC_LOG_V(DEBUG, TAG, "Read doxm.deviceuuid value = %s", strUuid);
607 ret = ConvertStrToUuid(strUuid, &doxm->deviceID);
608 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
614 if (IsPropertyReadOnly(DOXM_DEVICEUUID, stateForReadOnlyCheck))
622 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
623 memcpy(doxm->deviceID.id, &gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
627 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_DEVOWNERID_NAME, &doxmMap);
628 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
630 OIC_LOG(DEBUG, TAG, "Found doxm.devowneruuid tag in doxmMap.");
631 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
632 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding devowneruuid Value.");
633 OIC_LOG_V(DEBUG, TAG, "Read doxm.devowneruuid value = %s", strUuid);
634 ret = ConvertStrToUuid(strUuid , &doxm->owner);
635 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
641 if (IsPropertyReadOnly(DOXM_DEVOWNERUUID, stateForReadOnlyCheck))
649 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
650 memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
653 #ifdef MULTIPLE_OWNER
654 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
655 if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
657 OIC_LOG(DEBUG, TAG, "Found doxm.mom tag in doxmMap.");
659 cborFindResult = cbor_value_get_int(&doxmMap, &mode);
660 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
661 if(NULL == doxm->mom)
663 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
664 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
666 doxm->mom->mode = (OicSecMomType_t)mode;
669 if (IsPropertyReadOnly(DOXM_MOM, stateForReadOnlyCheck))
675 else if(NULL != gDoxm && NULL != gDoxm->mom)
677 // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
678 if(NULL == doxm->mom)
680 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
681 VERIFY_NOT_NULL(TAG, doxm->mom, ERROR);
683 doxm->mom->mode = gDoxm->mom->mode;
686 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
687 if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
689 OIC_LOG(DEBUG, TAG, "Found doxm.subowner tag in doxmMap.");
690 size_t subOwnerLen = 0;
691 CborValue subOwnerCbor;
692 cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
693 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
694 VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
696 cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
697 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
699 while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
701 OCStackResult convertRes = OC_STACK_ERROR;
702 OicSecSubOwner_t* subOwner = NULL;
703 char* strSubOwnerUuid = NULL;
706 cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strSubOwnerUuid, &uuidLen, NULL);
707 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
709 subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
710 VERIFY_NOT_NULL(TAG, subOwner, ERROR);
712 convertRes = ConvertStrToUuid(strSubOwnerUuid, &subOwner->uuid);
713 VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
714 subOwner->status = MOT_STATUS_DONE;
715 LL_APPEND(doxm->subOwners, subOwner);
717 cborFindResult = cbor_value_advance(&subOwnerCbor);
718 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
722 if (IsPropertyReadOnly(DOXM_SUBOWNER, stateForReadOnlyCheck))
728 else if(NULL != gDoxm && NULL != gDoxm->subOwners)
730 // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
731 OicSecSubOwner_t* subOwnerItor = NULL;
732 LL_FOREACH(gDoxm->subOwners, subOwnerItor)
734 OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
735 VERIFY_NOT_NULL(TAG, subOwnerId, ERROR);
737 memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
738 subOwnerId->status = MOT_STATUS_DONE;
740 LL_APPEND(doxm->subOwners, subOwnerId);
743 #endif //MULTIPLE_OWNER
746 cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
747 if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
749 OIC_LOG(DEBUG, TAG, "Found doxm.rowneruuid tag in doxmMap.");
750 cborFindResult = cbor_value_dup_text_string(&doxmMap, &strUuid , &len, NULL);
751 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding rowneruuid Value.");
752 OIC_LOG_V(DEBUG, TAG, "Read doxm.rowneruuid value = %s", strUuid);
753 ret = ConvertStrToUuid(strUuid , &doxm->rownerID);
754 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
760 if (IsPropertyReadOnly(DOXM_ROWNERUUID, stateForReadOnlyCheck))
768 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
769 memcpy(doxm->rownerID.id, gDoxm->rownerID.id, sizeof(doxm->rownerID.id));
776 if (CborNoError != cborFindResult)
778 OIC_LOG (ERROR, TAG, "CBORPayloadToDoxm failed!!!");
779 DeleteDoxmBinData(doxm);
782 ret = OC_STACK_ERROR;
788 * @todo document this function including why code might need to call this.
789 * The current suspicion is that it's not being called as much as it should.
791 static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
797 // Convert Doxm data into CBOR for update to persistent storage
798 uint8_t *payload = NULL;
800 OCStackResult res = DoxmToCBORPayload(doxm, &payload, &size);
801 if (payload && (OC_STACK_OK == res)
802 && (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, payload, size)))
810 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, NULL, 0))
819 static bool ValidateQuery(const char * query)
821 // Send doxm resource data if the state of doxm resource
822 // matches with the query parameters.
823 // else send doxm resource data as NULL
824 // TODO Remove this check and rely on Policy Engine
825 // and Provisioning Mode to enforce provisioning-state
826 // access rules. Eventually, the PE and PM code will
827 // not send a request to the /doxm Entity Handler at all
828 // if it should not respond.
829 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
835 bool bOwnedQry = false; // does querystring contains 'owned' query ?
836 bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
837 bool bDeviceIDQry = false; // does querystring contains 'deviceuuid' query ?
838 bool bDeviceIDMatch = false; // does 'deviceuuid' query matches with doxm.deviceuuid ?
839 bool bInterfaceQry = false; // does querystring contains 'if' query ?
840 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
841 #ifdef MULTIPLE_OWNER
842 bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
843 #endif //MULTIPLE_OWNER
845 OicParseQueryIter_t parseIter = {.attrPos = NULL};
847 ParseQueryIterInit((unsigned char*)query, &parseIter);
849 while (GetNextQuery(&parseIter))
851 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
854 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
859 else if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
866 #ifdef MULTIPLE_OWNER
867 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
869 OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
870 if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
872 if(GetNextQuery(&parseIter))
874 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
876 if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
886 #endif //MULTIPLE_OWNER
888 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
891 OicUuid_t subject = {.id={0}};
893 if (sizeof(subject.id) < parseIter.valLen)
895 OIC_LOG (ERROR, TAG, "Subject ID length is too long");
898 memcpy(subject.id, parseIter.valPos, parseIter.valLen);
899 if (0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
901 bDeviceIDMatch = true;
905 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
907 bInterfaceQry = true;
908 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
910 bInterfaceMatch = true;
912 return (bInterfaceQry ? bInterfaceMatch: true);
916 return ((bOwnedQry ? bOwnedMatch : true) &&
917 (bDeviceIDQry ? bDeviceIDMatch : true));
920 static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
922 OCEntityHandlerResult ehRet = OC_EH_OK;
924 OIC_LOG(DEBUG, TAG, "Doxm EntityHandle processing GET request");
926 //Checking if Get request is a query.
927 if (ehRequest->query)
929 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
930 OIC_LOG(DEBUG, TAG, "HandleDoxmGetRequest processing query");
931 if (!ValidateQuery(ehRequest->query))
938 * For GET or Valid Query request return doxm resource CBOR payload.
939 * For non-valid query return NULL json payload.
940 * A device will 'always' have a default Doxm, so DoxmToCBORPayload will
941 * return valid doxm resource json.
943 uint8_t *payload = NULL;
946 if (ehRet == OC_EH_OK)
948 if (OC_STACK_OK != DoxmToCBORPayload(gDoxm, &payload, &size))
950 OIC_LOG(WARNING, TAG, "DoxmToCBORPayload failed in HandleDoxmGetRequest");
954 OIC_LOG(DEBUG, TAG, "Send payload for doxm GET request");
955 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
957 // Send response payload to request originator
958 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
959 OC_EH_OK : OC_EH_ERROR;
966 OCStackResult DoxmUpdateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
968 OCStackResult result = OC_STACK_OK;
973 dst->oxmSel = src->oxmSel;
974 OIC_LOG_V(DEBUG, TAG, "%s: updated doxm.oxmsel = %d", __func__,
977 // Update devowneruuid
978 memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
979 #ifndef NDEBUG // if debug build, log the new uuid
980 char uuidString[UUID_STRING_SIZE] = { 0 };
981 bool convertedUUID = OCConvertUuidToString(dst->owner.id, uuidString);
984 OIC_LOG_V(DEBUG, TAG, "%s: updated doxm.devowneruuid = %s", __func__,
990 memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
991 #ifndef NDEBUG // if debug build, log the new uuid
992 convertedUUID = OCConvertUuidToString(dst->rownerID.id, uuidString);
995 OIC_LOG_V(DEBUG, TAG, "%s: updated doxm.rowneruuid = %s", __func__,
1000 // Update deviceuuid
1001 memcpy(&(dst->deviceID), &(src->deviceID), sizeof(OicUuid_t));
1002 #ifndef NDEBUG // if debug build, log the new uuid
1003 convertedUUID = OCConvertUuidToString(dst->deviceID.id, uuidString);
1006 OIC_LOG_V(DEBUG, TAG, "%s: updated doxm.deviceuuid = %s", __func__,
1011 // Update owned status
1012 if(dst->owned != src->owned)
1014 dst->owned = src->owned;
1015 OIC_LOG_V(DEBUG, TAG, "%s: updated owned = %s", __func__,
1016 dst->owned?"true":"false");
1019 #ifdef MULTIPLE_OWNER
1022 OIC_LOG(DEBUG, TAG, "Detected 'mom' property");
1023 if(NULL == dst->mom)
1025 dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
1026 if (NULL == dst->mom)
1028 result = OC_STACK_NO_MEMORY;
1032 if (NULL != dst->mom)
1034 dst->mom->mode = src->mom->mode;
1035 OIC_LOG_V(DEBUG, TAG, "%s: updated mom->mode = %d", __func__,
1036 (int)dst->mom->mode);
1039 #endif //MULTIPLE_OWNER
1045 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1046 #ifdef MULTIPLE_OWNER
1048 * Callback function to handle MOT DTLS handshake result.
1049 * @param[out] object remote device information.
1050 * @param[out] errorInfo CA Error information.
1052 CAResult_t MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
1053 const CAErrorInfo_t *errorInfo)
1055 OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
1057 if(CA_STATUS_OK == errorInfo->result)
1059 CASecureEndpoint_t authenticationSubOwnerInfo;
1060 CAResult_t caRes = CAGetSecureEndpointData(object, &authenticationSubOwnerInfo);
1061 if (CA_STATUS_OK == caRes)
1065 OIC_LOG_V(WARNING, TAG, "%s: gDoxm is NULL", __func__);
1066 return CA_HANDLE_ERROR_OTHER_MODULE;
1069 if (0 == memcmp(authenticationSubOwnerInfo.identity.id, gDoxm->owner.id,
1070 authenticationSubOwnerInfo.identity.id_length))
1072 OIC_LOG(WARNING, TAG, "Super owner tried MOT, this request will be ignored.");
1073 return CA_HANDLE_ERROR_OTHER_MODULE;
1076 OicSecSubOwner_t* subOwnerInst = NULL;
1077 LL_FOREACH(gDoxm->subOwners, subOwnerInst)
1079 if(0 == memcmp(subOwnerInst->uuid.id,
1080 authenticationSubOwnerInfo.identity.id,
1081 authenticationSubOwnerInfo.identity.id_length))
1087 if(NULL == subOwnerInst)
1089 subOwnerInst = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
1092 char* strUuid = NULL;
1093 if (sizeof(subOwnerInst->uuid.id) < authenticationSubOwnerInfo.identity.id_length)
1095 OIC_LOG(ERROR, TAG, "Identity id is too long");
1096 return CA_HANDLE_ERROR_OTHER_MODULE;
1098 memcpy(subOwnerInst->uuid.id, authenticationSubOwnerInfo.identity.id,
1099 authenticationSubOwnerInfo.identity.id_length);
1100 if(OC_STACK_OK != ConvertUuidToStr(&subOwnerInst->uuid, &strUuid))
1102 OIC_LOG(ERROR, TAG, "Failed to allocate memory.");
1103 return CA_HANDLE_ERROR_OTHER_MODULE;
1105 OIC_LOG_V(DEBUG, TAG, "Adding New SubOwner(%s)", strUuid);
1107 LL_APPEND(gDoxm->subOwners, subOwnerInst);
1108 if(!UpdatePersistentStorage(gDoxm))
1110 OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
1117 OIC_LOG_V(ERROR, TAG, "Could not CAGetSecureEndpointData: %d", caRes);
1121 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
1123 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
1126 OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
1127 return CA_STATUS_OK;
1129 #endif //MULTIPLE_OWNER
1130 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1133 * Function to validate oxmsel with oxms.
1135 * @param[in] supportedMethods Array of supported methods
1136 * @param[in] numberOfMethods number of supported methods
1137 * @param[out] selectedMethod Selected methods
1138 * @return TRUE on success
1140 static bool ValidateOxmsel(const OicSecOxm_t *supportedMethods,
1141 size_t numberOfMethods, OicSecOxm_t *selectedMethod)
1143 bool isValidOxmsel = false;
1145 OIC_LOG(DEBUG, TAG, "IN ValidateOxmsel");
1146 if (numberOfMethods == 0 || !supportedMethods)
1148 OIC_LOG(WARNING, TAG, "Could not find a supported OxM.");
1149 return isValidOxmsel;
1152 for (size_t i = 0; i < numberOfMethods; i++)
1154 if (*selectedMethod == supportedMethods[i])
1156 isValidOxmsel = true;
1162 OIC_LOG(ERROR, TAG, "Not allowed Oxmsel.");
1163 return isValidOxmsel;
1166 OIC_LOG(DEBUG, TAG, "OUT ValidateOxmsel");
1168 return isValidOxmsel;
1171 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1172 static CAResult_t DoxmDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
1174 OIC_LOG_V(DEBUG, TAG, "In %s(%p, %p)", __func__, endpoint, info);
1176 if ((NULL != endpoint) && (NULL != info) && (CA_STATUS_OK == info->result))
1179 * Allow this OBT endpoint to bypass ACE checks for SVRs, while this
1180 * device is not yet owned.
1182 OC_VERIFY(CASetSecureEndpointAttribute(endpoint,
1183 CA_SECURE_ENDPOINT_ATTRIBUTE_ADMINISTRATOR));
1186 OIC_LOG_V(DEBUG, TAG, "Out %s(%p, %p)", __func__, endpoint, info);
1187 return CA_STATUS_OK;
1190 static void RegisterOTMSslHandshakeCallback(CAHandshakeErrorCallback callback)
1192 OC_VERIFY(CA_STATUS_OK == CAregisterSslHandshakeCallback(callback));
1195 #ifdef MULTIPLE_OWNER
1196 void HandleDoxmPostRequestMom(OicSecDoxm_t *newDoxm, OCEntityHandlerRequest *ehRequest)
1198 OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1202 if (OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
1204 CAResult_t caRes = CA_STATUS_FAILED;
1205 if (OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
1207 caRes = CAEnableAnonECDHCipherSuite(false);
1208 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1209 OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1211 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1212 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1213 (CATransportAdapter_t)ehRequest->devAddr.adapter);
1214 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1215 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1217 //Set the device id to derive temporal PSK
1218 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1222 OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1225 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1229 //if MOM is disabled, revert the DTLS handshake callback
1230 if (CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
1232 OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
1237 if (newDoxm->subOwners)
1239 OicSecSubOwner_t *subowner = NULL;
1240 OicSecSubOwner_t *temp = NULL;
1242 OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
1244 if (gDoxm->subOwners)
1246 LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
1248 LL_DELETE(gDoxm->subOwners, subowner);
1255 LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
1257 LL_DELETE(newDoxm->subOwners, subowner);
1258 LL_APPEND(gDoxm->subOwners, subowner);
1262 OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1264 #endif //MULTIPLE_OWNER
1265 #endif // __WITH_DTLS__ or __WITH_TLS__
1267 int HandleDoxmPostRequestSVR()
1269 OCStackResult ownerRes = SetAclRownerId(&gDoxm->owner);
1270 if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1272 OIC_LOG_V(ERROR, TAG, "%s: set acl RownerId", __func__);
1275 ownerRes = SetCredRownerId(&gDoxm->owner);
1276 if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1278 OIC_LOG_V(ERROR, TAG, "%s: set cred RownerId", __func__);
1281 ownerRes = SetPstatRownerId(&gDoxm->owner);
1282 if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1284 OIC_LOG_V(ERROR, TAG, "%s: set pstat RownerId", __func__);
1287 ownerRes = SetDpairingRownerId(&gDoxm->owner);
1288 if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1290 OIC_LOG_V(ERROR, TAG, "%s: set dpairing RownerId", __func__);
1293 ownerRes = SetPconfRownerId(&gDoxm->owner);
1294 if (OC_STACK_OK != ownerRes && OC_STACK_NO_RESOURCE != ownerRes)
1296 OIC_LOG_V(ERROR, TAG, "%s: set pconf RownerId", __func__);
1303 OCEntityHandlerResult HandleDoxmPostRequestUpdatePS(bool fACE)
1305 //Update new state in persistent storage
1306 if (UpdatePersistentStorage(gDoxm) == true)
1308 //Update default ACE of security resource to prevent anonymous user access.
1311 if (OC_STACK_OK == UpdateDefaultSecProvACE())
1317 OIC_LOG_V(ERROR, TAG, "%s: Failed to remove default ACL for security provisioning", __func__);
1325 OIC_LOG_V(ERROR, TAG, "%s: Failed to update DOXM in persistent storage", __func__);
1330 OCEntityHandlerResult HandleDoxmPostRequestJustWork(OicSecDoxm_t *newDoxm,
1331 OCEntityHandlerRequest *ehRequest,
1332 bool isDuplicatedMsg)
1334 OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1335 OCEntityHandlerResult ehRet = OC_EH_OK;
1337 #if !(defined(__WITH_DTLS__) || defined(__WITH_TLS__))
1338 OC_UNUSED(isDuplicatedMsg);
1339 OC_UNUSED(ehRequest);
1340 #endif // not __WITH_DTLS__ and not __WITH_TLS__
1342 if (IsNilUuid(&newDoxm->owner))
1344 gDoxm->oxmSel = newDoxm->oxmSel;
1345 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1346 OCStackResult res = EnableAnonCipherSuiteIfUnOwnedAndJustWorksSelected(NULL);
1347 if (OC_STACK_OK != res)
1349 ehRet = OC_EH_ERROR;
1351 #endif // __WITH_DTLS__ or __WITH_TLS__
1356 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1357 //Save the owner's UUID to derive owner credential
1358 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1361 * Disable anonymous ECDH cipher in tinyDTLS since device is now
1364 RegisterOTMSslHandshakeCallback(NULL);
1365 CAResult_t caRes = CA_STATUS_OK;
1366 caRes = CAEnableAnonECDHCipherSuite(false);
1367 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1368 OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1370 //In case of Mutual Verified Just-Works, verify mutualVerifNum
1371 if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned &&
1372 false == isDuplicatedMsg)
1374 uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0};
1375 uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0};
1376 OicUuid_t deviceID = {.id = {0}};
1378 //Generate mutualVerifNum
1379 OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
1381 char label[LABEL_LEN] = {0};
1382 snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS);
1383 if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))
1385 OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
1386 ehRet = OC_EH_ERROR;
1391 CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
1394 gDoxm->owner.id, sizeof(gDoxm->owner.id),
1395 gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
1396 preMutualVerifNum, OWNER_PSK_LENGTH_128);
1397 if (CA_STATUS_OK != pskRet)
1399 OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential");
1400 ehRet = OC_EH_ERROR;
1405 memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum),
1406 sizeof(mutualVerifNum));
1408 //Wait for user confirmation
1409 if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM))
1411 ehRet = OC_EH_NOT_ACCEPTABLE;
1418 #endif // __WITH_DTLS__ or __WITH_TLS__
1421 OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1425 OCEntityHandlerResult HandleDoxmPostRequestRandomPin(OicSecDoxm_t *newDoxm,
1426 OCEntityHandlerRequest *ehRequest,
1427 bool isDuplicatedMsg)
1429 OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1430 OCEntityHandlerResult ehRet = OC_EH_OK;
1432 #if !(defined(__WITH_DTLS__) || defined(__WITH_TLS__))
1433 OC_UNUSED(isDuplicatedMsg);
1434 OC_UNUSED(ehRequest);
1435 #endif // not __WITH_DTLS__ and not __WITH_TLS__
1437 if (IsNilUuid(&newDoxm->owner))
1439 gDoxm->oxmSel = newDoxm->oxmSel;
1441 * If current state of the device is un-owned, enable
1442 * ECDHE_PSK cipher so that the Provisioning tool can
1443 * initiate the ownership transfer.
1445 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1446 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1447 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1448 OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1450 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1451 caRes = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
1452 (CATransportAdapter_t)ehRequest->devAddr.adapter);
1453 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1455 if (!isDuplicatedMsg)
1457 char ranPin[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1458 if (OC_STACK_OK == GeneratePin(ranPin, sizeof(ranPin)))
1460 //Set the device id to derive temporal PSK
1461 SetUuidForPinBasedOxm(&gDoxm->deviceID);
1464 * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
1465 * Credential should not be saved into SVR.
1466 * For this reason, use a temporary get_psk_info callback to random PIN OxM.
1468 caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
1469 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1474 OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
1475 ehRet = OC_EH_ERROR;
1478 #endif // __WITH_DTLS__ or __WITH_TLS__
1480 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1483 //Save the owner's UUID to derive owner credential
1484 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1486 // In case of random-pin based OTM, close the PIN display if callback is registered.
1487 if (!isDuplicatedMsg)
1492 #endif // __WITH_DTLS__ or __WITH_TLS__
1495 OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1499 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1500 OCEntityHandlerResult HandleDoxmPostRequestMfg(OicSecDoxm_t *newDoxm,
1501 OCEntityHandlerRequest *ehRequest,
1502 bool isDuplicatedMsg)
1504 OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1505 OCEntityHandlerResult ehRet = OC_EH_OK;
1508 //In case of Confirm Manufacturer Cert, get user confirmation
1509 if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned &&
1510 false == isDuplicatedMsg && !IsNilUuid(&newDoxm->owner))
1512 if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM))
1514 ehRet = OC_EH_NOT_ACCEPTABLE;
1523 //Save the owner's UUID to derive owner credential
1524 memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
1525 gDoxm->oxmSel = newDoxm->oxmSel;
1527 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1528 CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
1529 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1530 OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1532 //Unset pre-selected ciphersuite, if any
1533 caRes = CASelectCipherSuite(0,(CATransportAdapter_t)ehRequest->devAddr.adapter);
1534 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1535 OIC_LOG(DEBUG, TAG, "No ciphersuite preferred");
1537 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
1538 VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(
1539 InitManufacturerCipherSuiteList), ERROR);
1541 OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1544 #endif // __WITH_DTLS__ or __WITH_TLS__
1546 //Change the SVR's resource owner as owner device.
1547 OCEntityHandlerResult HandleDoxmPostRequestSrv(OicSecDoxm_t *newDoxm,
1548 OCEntityHandlerRequest *ehRequest,
1549 bool isDuplicatedMsg)
1551 OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1552 OCEntityHandlerResult ehRet = OC_EH_OK;
1554 switch (newDoxm->oxmSel)
1556 case OIC_JUST_WORKS:
1557 case OIC_MV_JUST_WORKS:
1558 ehRet = HandleDoxmPostRequestJustWork(newDoxm, ehRequest, isDuplicatedMsg);
1560 case OIC_RANDOM_DEVICE_PIN:
1561 ehRet = HandleDoxmPostRequestRandomPin(newDoxm, ehRequest, isDuplicatedMsg);
1563 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1564 case OIC_MANUFACTURER_CERTIFICATE:
1565 case OIC_CON_MFG_CERT:
1566 ehRet = HandleDoxmPostRequestMfg(newDoxm, ehRequest, isDuplicatedMsg);
1568 #endif // __WITH_DTLS__ or __WITH_TLS__
1573 OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
1578 static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest *ehRequest)
1580 OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
1581 OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
1582 static uint16_t previousMsgId = 0;
1583 bool isDuplicatedMsg = false;
1586 * Convert CBOR Doxm data into binary. This will also validate
1587 * the Doxm data received.
1589 OicSecDoxm_t *newDoxm = NULL;
1591 VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
1592 VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
1594 uint8_t *payload = ((OCSecurityPayload *)ehRequest->payload)->securityData;
1595 VERIFY_NOT_NULL(TAG, payload, ERROR);
1596 size_t size = ((OCSecurityPayload *)ehRequest->payload)->payloadSize;
1597 bool roParsed = false;
1598 OicSecDostype_t onboardingState;
1600 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&onboardingState), ERROR);
1601 OCStackResult res = CBORPayloadToDoxmBin(payload, size, &newDoxm, &roParsed,
1602 onboardingState.state);
1603 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1604 VERIFY_NOT_NULL(TAG, newDoxm, ERROR);
1607 * message ID is supported for CoAP over UDP only according to RFC 7252
1608 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
1609 * In case of other transport adapter, duplicate message check is not required.
1611 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
1612 previousMsgId == ehRequest->messageID)
1614 isDuplicatedMsg = true;
1617 // Check request on RO property
1618 if (true == roParsed)
1620 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
1621 ehRet = OC_EH_NOT_ACCEPTABLE;
1625 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
1628 if (true == gDoxm->owned)
1630 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1632 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel is not supported on Server");
1633 ehRet = OC_EH_NOT_ACCEPTABLE;
1637 // Update gDoxm based on newDoxm
1638 res = DoxmUpdateWriteableProperty(newDoxm, gDoxm);
1639 if (OC_STACK_OK != res)
1642 "gDoxm properties were not able to be updated so we cannot handle the request.");
1643 ehRet = OC_EH_ERROR;
1647 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1648 #ifdef MULTIPLE_OWNER
1649 HandleDoxmPostRequestMom(newDoxm, ehRequest);
1650 #endif //MULTIPLE_OWNER
1651 #endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1653 //Update new state in persistent storage
1654 ehRet = HandleDoxmPostRequestUpdatePS(false);
1659 // TODO [IOT-2107] this logic assumes that the only POST to /doxm in
1660 // unowned state is either a) changing to owned or b) setting oxmsel and
1661 // therefore (in case b) should enable the proper cipher for OTM. But it's
1662 // allowable for Client to be posting other things such as /doxm.rowneruuid
1663 // when owned == false, too. Added a workaround (see 'workaround' below)
1664 // but this POST handler needs to be fixed per IOT-2107.
1665 if ((false == gDoxm->owned) && (false == newDoxm->owned))
1667 if (false == ValidateOxmsel(gDoxm->oxm, gDoxm->oxmLen, &newDoxm->oxmSel))
1669 OIC_LOG(ERROR, TAG, "Not acceptable request because oxmsel does not support on Server");
1670 ehRet = OC_EH_NOT_ACCEPTABLE;
1675 // We wouldn't be at this point in the
1676 // code if the POST contained R-only Properties for the current /pstat.dos.s
1677 // state, so we want to update writeable properties now that we've validated
1678 // oxmsel is a valid oxm for this device.
1679 res = DoxmUpdateWriteableProperty(newDoxm, gDoxm);
1680 if (OC_STACK_OK != res)
1683 "gDoxm properties were not able to be updated so we cannot handle the request.");
1684 ehRet = OC_EH_ERROR;
1688 ehRet = HandleDoxmPostRequestSrv(newDoxm, ehRequest, isDuplicatedMsg);
1689 VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
1691 // Update new state in persistent storage
1692 ehRet = HandleDoxmPostRequestUpdatePS(false);
1696 * When current state of the device is un-owned and Provisioning
1697 * Tool is attempting to change the state to 'Owned' with a
1698 * qualified value for the field 'Owner'
1700 // TODO [IOT-2107] reconcile POST handler behavior with Specification
1701 if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
1702 UuidCmp(&gDoxm->owner, &newDoxm->owner))
1704 if (HandleDoxmPostRequestSVR())
1706 ehRet = OC_EH_ERROR;
1710 gDoxm->owned = true;
1711 memcpy(&gDoxm->rownerID, &gDoxm->owner, sizeof(OicUuid_t));
1713 // Update new state in persistent storage
1714 ehRet = HandleDoxmPostRequestUpdatePS(true);
1716 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1717 if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel ||
1718 OIC_CON_MFG_CERT == gDoxm->oxmSel)
1720 CAregisterPkixInfoHandler(GetPkixInfo);
1721 CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
1723 #endif // __WITH_DTLS__ or __WITH_TLS__
1726 if (OC_EH_OK != ehRet)
1729 * If some error is occured while ownership transfer,
1730 * ownership transfer related resource should be revert back to initial status.
1736 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
1738 if (!isDuplicatedMsg)
1740 RestoreDoxmToInitState();
1741 RestorePstatToInitState();
1742 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
1748 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
1753 previousMsgId = ehRequest->messageID;
1756 //Send payload to request originator
1757 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1758 OC_EH_OK : OC_EH_ERROR;
1760 DeleteDoxmBinData(newDoxm);
1762 OIC_LOG_V (DEBUG, TAG, "%s: OUT", __func__);
1768 OCEntityHandlerResult DoxmEntityHandler(OCEntityHandlerFlag flag,
1769 OCEntityHandlerRequest * ehRequest,
1770 void* callbackParam)
1772 (void)callbackParam;
1773 OCEntityHandlerResult ehRet = OC_EH_ERROR;
1775 if(NULL == ehRequest)
1780 if (flag & OC_REQUEST_FLAG)
1782 OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1784 switch (ehRequest->method)
1787 ehRet = HandleDoxmGetRequest(ehRequest);
1791 ehRet = HandleDoxmPostRequest(ehRequest);
1795 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
1796 OC_EH_OK : OC_EH_ERROR;
1804 OCStackResult CreateDoxmResource()
1806 OCStackResult ret = OCCreateResource(&gDoxmHandle,
1807 OIC_RSRC_TYPE_SEC_DOXM,
1808 OC_RSRVD_INTERFACE_DEFAULT,
1812 OC_SECURE | OC_NONSECURE |
1815 if (OC_STACK_OK != ret)
1817 OIC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
1818 DeInitDoxmResource();
1824 * Checks if DeviceID is generated during provisioning for the new device.
1825 * If DeviceID is NULL then generates the new DeviceID.
1826 * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
1828 static OCStackResult CheckDeviceID()
1830 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1832 OCStackResult ret = OC_STACK_ERROR;
1833 bool validId = false;
1835 VERIFY_NOT_NULL_RETURN(TAG, gDoxm, ERROR, OC_STACK_INVALID_PARAM);
1837 for (uint8_t i = 0; i < UUID_LENGTH; i++)
1839 if (gDoxm->deviceID.id[i] != 0)
1848 char* strUuid = NULL;
1849 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
1850 //If seed value is exists, generate UUID using seed with SHA256
1851 if (0 != gUuidSeedSize)
1853 uint8_t hashVal[MBEDTLS_MD_MAX_SIZE] = {0};
1856 OIC_LOG(DEBUG, TAG, "UUID will be generated using seed w/ SHA256");
1857 OIC_LOG(DEBUG, TAG, "Seed value : ");
1858 OIC_LOG_BUFFER(DEBUG, TAG, gUuidSeed, gUuidSeedSize);
1860 mbedret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
1861 gUuidSeed, gUuidSeedSize, hashVal);
1864 memcpy(gDoxm->deviceID.id, hashVal, sizeof(gDoxm->deviceID.id));
1869 OIC_LOG_V(ERROR, TAG, "mbedtls_md error : %d", mbedret);
1870 ret = OC_STACK_ERROR;
1875 if (!OCGenerateUuid(gDoxm->deviceID.id))
1877 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1878 ret = OC_STACK_ERROR;
1886 if (!OCGenerateUuid(gDoxm->deviceID.id))
1888 OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
1889 ret = OC_STACK_ERROR;
1897 if (OC_STACK_OK == ConvertUuidToStr(&gDoxm->deviceID, &strUuid))
1899 OIC_LOG_V(DEBUG, TAG, "Generated device UUID is [%s]", strUuid);
1904 OIC_LOG(WARNING, TAG, "Failed to convert UUID to string");
1908 if (!UpdatePersistentStorage(gDoxm))
1910 //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
1911 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
1919 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
1925 * Get the default value.
1927 * @return the default value of doxm, @ref OicSecDoxm_t.
1929 static OicSecDoxm_t* GetDoxmDefault()
1931 OIC_LOG(DEBUG, TAG, "GetDoxmToDefault");
1932 return &gDefaultDoxm;
1935 const OicSecDoxm_t* GetDoxmResourceData()
1940 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1942 * Internal API to prepare MOT
1944 static void PrepareMOT(const OicSecDoxm_t* doxm)
1946 OIC_LOG(INFO, TAG, "IN PrepareMOT");
1947 VERIFY_NOT_NULL(TAG, doxm, ERROR);
1949 if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
1951 CAResult_t caRes = CA_STATUS_FAILED;
1953 OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
1955 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
1957 caRes = CAEnableAnonECDHCipherSuite(false);
1958 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1959 OIC_LOG_V(INFO, TAG, "%s: ECDH_ANON CipherSuite is DISABLED", __func__);
1961 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
1962 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP);
1963 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1965 caRes = CASelectCipherSuite((uint16_t)MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_TCP);
1966 VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
1968 OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
1970 //Set the device id to derive temporal PSK
1971 SetUuidForPinBasedOxm(&doxm->deviceID);
1975 OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
1979 CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
1982 OIC_LOG(INFO, TAG, "OUT PrepareMOT");
1985 OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
1987 #endif //defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
1989 OCStackResult InitDoxmResource()
1991 OCStackResult ret = OC_STACK_ERROR;
1993 //Read DOXM resource from PS
1994 uint8_t *data = NULL;
1996 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_DOXM_NAME, &data, &size);
1997 // If database read failed
1998 if (OC_STACK_OK != ret)
2000 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
2004 // Read DOXM resource from PS
2005 ret = CBORPayloadToDoxm(data, size, &gDoxm);
2008 * If SVR database in persistent storage got corrupted or
2009 * is not available for some reason, a default doxm is created
2010 * which allows user to initiate doxm provisioning again.
2012 if ((OC_STACK_OK != ret) || !data || !gDoxm)
2014 gDoxm = GetDoxmDefault();
2017 //In case of the server is shut down unintentionally, we should initialize the owner
2018 if(gDoxm && (false == gDoxm->owned))
2020 OicUuid_t emptyUuid = {.id={0}};
2021 memcpy(&gDoxm->owner, &emptyUuid, sizeof(OicUuid_t));
2024 ret = CheckDeviceID();
2025 if (ret == OC_STACK_OK)
2027 OIC_LOG_V(DEBUG, TAG, "Initial Doxm Owned = %d", gDoxm->owned);
2028 //Instantiate 'oic.sec.doxm'
2029 ret = CreateDoxmResource();
2033 OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
2037 #if defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2038 //if MOT is enabled, MOT should be prepared.
2039 if(gDoxm && gDoxm->owned)
2043 #endif // defined(__WITH_DTLS__) && defined(MULTIPLE_OWNER)
2045 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2046 bool isAnonEnabled = false;
2047 if (OC_STACK_OK != EnableAnonCipherSuiteIfUnOwnedAndJustWorksSelected(&isAnonEnabled))
2049 ret = OC_STACK_ERROR;
2051 OIC_LOG_V(INFO, TAG, "%s: Anon Ciphersuite %sENABLED.", __func__,
2052 isAnonEnabled ? "" : "NOT ");
2053 #endif // __WITH_DTLS__ or __WITH_TLS__
2058 OCStackResult DeInitDoxmResource()
2060 OCStackResult ret = OCDeleteResource(gDoxmHandle);
2061 if (gDoxm != &gDefaultDoxm)
2063 DeleteDoxmBinData(gDoxm);
2067 if (OC_STACK_OK == ret)
2073 return OC_STACK_ERROR;
2077 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
2078 OCStackResult SetDoxmDeviceIDSeed(const uint8_t* seed, size_t seedSize)
2080 OIC_LOG_V(INFO, TAG, "In %s", __func__);
2084 return OC_STACK_INVALID_PARAM;
2086 if (MAX_UUID_SEED_SIZE < seedSize)
2088 OIC_LOG_V(ERROR, TAG, "Seed size is too long (MAX size is %d bytes)", MAX_UUID_SEED_SIZE);
2089 return OC_STACK_INVALID_PARAM;
2091 if (MIN_UUID_SEED_SIZE > seedSize)
2093 OIC_LOG_V(ERROR, TAG, "Seed size is too small (MIN size is %d bytes)", MIN_UUID_SEED_SIZE);
2094 return OC_STACK_INVALID_PARAM;
2097 memset(gUuidSeed, 0x00, sizeof(gUuidSeed));
2098 memcpy(gUuidSeed, seed, seedSize);
2099 gUuidSeedSize = seedSize;
2101 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
2107 OCStackResult GetDoxmDeviceID(OicUuid_t *deviceuuid)
2109 if (deviceuuid && gDoxm)
2111 *deviceuuid = gDoxm->deviceID;
2114 return OC_STACK_ERROR;
2117 OCStackResult SetDoxmDeviceID(const OicUuid_t *deviceuuid)
2119 bool isOwnerUpdated = false;
2120 bool isRownerUpdated = false;
2121 if (NULL == deviceuuid)
2123 return OC_STACK_INVALID_PARAM;
2127 OIC_LOG(ERROR, TAG, "Doxm resource is not initialized.");
2128 return OC_STACK_NO_RESOURCE;
2131 #ifdef __WITH_DTLS__
2132 //for normal device.
2133 if (true == gDoxm->owned &&
2134 memcmp(gDoxm->deviceID.id, gDoxm->owner.id, sizeof(gDoxm->owner.id)) != 0)
2136 OIC_LOG(ERROR, TAG, "This device owned by owner's device.");
2137 OIC_LOG(ERROR, TAG, "Device UUID cannot be changed to guarantee the reliability of the connection.");
2138 return OC_STACK_ERROR;
2140 #endif //__WITH_DTLS
2142 //Save the previous UUID
2144 memcpy(prevUuid.id, gDoxm->deviceID.id, sizeof(prevUuid.id));
2146 //Change the device UUID
2147 memcpy(gDoxm->deviceID.id, deviceuuid->id, sizeof(gDoxm->deviceID.id));
2149 //Change the owner ID if necessary
2150 if (memcmp(gDoxm->owner.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2152 memcpy(gDoxm->owner.id, deviceuuid->id, sizeof(gDoxm->owner.id));
2153 isOwnerUpdated = true;
2155 //Change the resource owner ID if necessary
2156 // TODO [IOT-2023] change this behavior and upate the usage of this function
2157 // so that rowneruuid for each resource is set by OBT
2158 if (memcmp(gDoxm->rownerID.id, prevUuid.id, sizeof(prevUuid.id)) == 0)
2160 memcpy(gDoxm->rownerID.id, deviceuuid->id, sizeof(gDoxm->rownerID.id));
2161 isRownerUpdated = true;
2165 if (!UpdatePersistentStorage(gDoxm))
2167 //revert UUID in case of PSI error
2168 memcpy(gDoxm->deviceID.id, prevUuid.id, sizeof(gDoxm->deviceID.id));
2171 memcpy(gDoxm->owner.id, prevUuid.id, sizeof(gDoxm->owner.id));
2173 if (isRownerUpdated)
2175 memcpy(gDoxm->rownerID.id, prevUuid.id, sizeof(gDoxm->rownerID.id));
2178 OIC_LOG(ERROR, TAG, "Failed to update persistent storage");
2179 return OC_STACK_ERROR;
2184 OCStackResult GetDoxmDevOwnerId(OicUuid_t *devowneruuid)
2186 if (gDoxm && devowneruuid)
2188 memcpy(&(devowneruuid->id), &(gDoxm->owner.id), sizeof(devowneruuid->id));
2191 return OC_STACK_ERROR;
2194 OCStackResult SetDoxmDevOwnerId(const OicUuid_t *devowneruuid)
2196 if (gDoxm && devowneruuid)
2198 memcpy(&(gDoxm->owner.id), &(devowneruuid->id), sizeof(gDoxm->owner.id));
2201 return OC_STACK_ERROR;
2204 OCStackResult GetDoxmIsOwned(bool *isowned)
2206 if (isowned && gDoxm)
2208 *isowned = gDoxm->owned;
2211 return OC_STACK_ERROR;
2214 OCStackResult SetDoxmIsOwned(const bool isowned)
2218 gDoxm->owned = isowned;
2221 return OC_STACK_ERROR;
2224 OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid)
2226 if (gDoxm && rowneruuid)
2228 memcpy(&(rowneruuid->id), &(gDoxm->rownerID.id), sizeof(rowneruuid->id));
2231 return OC_STACK_ERROR;
2234 OCStackResult SetDoxmRownerId(const OicUuid_t *rowneruuid)
2236 if (gDoxm && rowneruuid)
2238 memcpy(&(gDoxm->rownerID.id), &(rowneruuid->id), sizeof(gDoxm->rownerID.id));
2241 return OC_STACK_ERROR;
2244 #ifdef MULTIPLE_OWNER
2246 * Compare the UUID to SubOwner.
2248 * @param[in] uuid device UUID
2250 * @return true if context->subjectId exist subowner list, else false.
2252 bool IsSubOwner(const OicUuid_t* uuid)
2254 bool retVal = false;
2261 if (gDoxm && gDoxm->subOwners)
2263 if (memcmp(gDoxm->owner.id, uuid->id, sizeof(gDoxm->owner.id)) == 0)
2268 OicSecSubOwner_t* subOwner = NULL;
2269 LL_FOREACH(gDoxm->subOwners, subOwner)
2271 if (memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
2280 OCStackResult SetMOTStatus(bool enable)
2282 OCStackResult ret = OC_STACK_NO_MEMORY;
2283 uint8_t *cborPayload = NULL;
2285 bool isDeallocateRequired = false;
2287 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
2289 VERIFY_NOT_NULL(TAG, gDoxm, ERROR);
2291 if (NULL == gDoxm->mom && !enable)
2293 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
2297 if (NULL == gDoxm->mom)
2299 gDoxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
2300 VERIFY_NOT_NULL(TAG, gDoxm->mom, ERROR);
2301 isDeallocateRequired = true;
2304 gDoxm->mom->mode = (enable ? OIC_MULTIPLE_OWNER_ENABLE : OIC_MULTIPLE_OWNER_DISABLE);
2306 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size);
2307 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2309 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2310 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2312 isDeallocateRequired = false;
2315 if (isDeallocateRequired)
2317 OICFree(gDoxm->mom);
2319 OICFree(cborPayload);
2320 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, ret);
2324 #endif //MULTIPLE_OWNER
2327 * Function to restore doxm resurce to initial status.
2328 * This function will use in case of error while ownership transfer
2330 void RestoreDoxmToInitState()
2334 OIC_LOG(INFO, TAG, "DOXM resource will revert back to initial status.");
2336 OicUuid_t emptyUuid = {.id={0}};
2337 memcpy(&(gDoxm->owner), &emptyUuid, sizeof(OicUuid_t));
2338 gDoxm->owned = false;
2339 gDoxm->oxmSel = OIC_JUST_WORKS;
2341 if(!UpdatePersistentStorage(gDoxm))
2343 OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
2348 OCStackResult SetDoxmSelfOwnership(const OicUuid_t* newROwner)
2350 OCStackResult ret = OC_STACK_ERROR;
2351 uint8_t *cborPayload = NULL;
2356 ret = OC_STACK_NO_RESOURCE;
2360 if( newROwner && (false == gDoxm->owned) )
2362 gDoxm->owned = true;
2363 memcpy(gDoxm->owner.id, newROwner->id, sizeof(newROwner->id));
2364 memcpy(gDoxm->rownerID.id, newROwner->id, sizeof(newROwner->id));
2366 ret = DoxmToCBORPayload(gDoxm, &cborPayload, &size);
2367 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2369 ret = UpdateSecureResourceInPS(OIC_JSON_DOXM_NAME, cborPayload, size);
2370 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
2372 OICFree(cborPayload);
2378 OICFree(cborPayload);
2382 #ifdef MULTIPLE_OWNER
2383 /** This function checks if two sets of /oic/sec/doxm MOT-specific properties are identical.
2385 * @param doxm1 is a pointer to the first @ref OicSecDoxm_t data.
2386 * @param doxm2 is a pointer to the second @ref OicSecDoxm_t data.
2388 * @return true if all of the properties are identical, else false.
2390 static bool AreDoxmBinMOTPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2392 //Compare the subOwners lists.
2393 OicSecSubOwner_t* subOwner1 = doxm1->subOwners;
2394 OicSecSubOwner_t* subOwner2 = doxm2->subOwners;
2398 if ((NULL == subOwner1) && (NULL == subOwner2))
2400 //Reached the end of both lists, so the two lists were identical.
2404 if ((NULL != subOwner1) && (NULL != subOwner2))
2406 if (0 != memcmp(&subOwner1->uuid, &subOwner2->uuid, sizeof(subOwner1->uuid)))
2408 OIC_LOG_V(ERROR, TAG, "%s: subOwner uuid mismatch", __func__);
2412 if (subOwner1->status != subOwner2->status)
2414 OIC_LOG_V(ERROR, TAG, "%s: subOwner status mismatch: (%u, %u)",
2415 __func__, (uint32_t)subOwner1->status, (uint32_t)subOwner2->status);
2419 //Go to the next elements from the two lists.
2420 subOwner1 = subOwner1->next;
2421 subOwner2 = subOwner2->next;
2425 OIC_LOG_V(ERROR, TAG, "%s: subOwner list length mismatch", __func__);
2429 // Compare the mom values.
2430 if (NULL == doxm1->mom)
2432 if (NULL != doxm2->mom)
2434 OIC_LOG_V(ERROR, TAG, "%s: doxm1->mom is NULL", __func__);
2441 if (NULL == doxm2->mom)
2443 OIC_LOG_V(ERROR, TAG, "%s: doxm2->mom is NULL", __func__);
2447 if (doxm1->mom->mode != doxm2->mom->mode)
2449 OIC_LOG_V(ERROR, TAG, "%s: mom->mode mismatch: (%u, %u)",
2450 __func__, (uint32_t)doxm1->mom->mode, (uint32_t)doxm2->mom->mode);
2456 #endif //#ifdef MULTIPLE_OWNER
2458 bool AreDoxmBinPropertyValuesEqual(OicSecDoxm_t* doxm1, OicSecDoxm_t* doxm2)
2460 if (NULL == doxm1 || NULL == doxm2)
2462 OIC_LOG_V(ERROR, TAG, "%s: unxpected NULL doxm pointer", __func__);
2466 //Compare the contents of the oxm array and its length oxmLen.
2467 size_t arrayLength = doxm1->oxmLen;
2469 if (arrayLength != doxm2->oxmLen)
2471 OIC_LOG_V(ERROR, TAG, "%s: oxmLen mismatch: (%" PRIuPTR ", %" PRIuPTR ")",
2472 __func__, arrayLength, doxm2->oxmLen);
2476 for (size_t i = 0; i < arrayLength; i++)
2478 if (doxm1->oxm[i] != doxm2->oxm[i])
2480 OIC_LOG_V(ERROR, TAG, "%s: oxm mismatch: (%u, %u)",
2481 __func__, (uint32_t)doxm1->oxm[i], (uint32_t)doxm2->oxm[i]);
2486 //Compare the remaining property values.
2487 if (doxm1->oxmSel != doxm2->oxmSel)
2489 OIC_LOG_V(ERROR, TAG, "%s: oxmSel mismatch: (%u, %u)",
2490 __func__, (uint32_t)doxm1->oxmSel, (uint32_t)doxm2->oxmSel);
2494 if (doxm1->sct != doxm2->sct)
2496 OIC_LOG_V(ERROR, TAG, "%s: sct mismatch: (%u, %u)",
2497 __func__, (uint32_t)doxm1->sct, (uint32_t)doxm2->sct);
2501 if (doxm1->owned != doxm2->owned)
2503 OIC_LOG_V(ERROR, TAG, "%s: owned mismatch: (%u, %u)",
2504 __func__, (uint32_t)doxm1->owned, (uint32_t)doxm2->owned);
2508 if (0 != memcmp(&doxm1->deviceID, &doxm2->deviceID, sizeof(doxm1->deviceID)))
2510 OIC_LOG_V(ERROR, TAG, "%s: deviceID mismatch", __func__);
2514 if (doxm1->dpc != doxm2->dpc)
2516 OIC_LOG_V(ERROR, TAG, "%s: dpc mismatch: (%u, %u)",
2517 __func__, (uint32_t)doxm1->dpc, (uint32_t)doxm2->dpc);
2521 if (0 != memcmp(&doxm1->owner, &doxm2->owner, sizeof(doxm1->owner)))
2523 OIC_LOG_V(ERROR, TAG, "%s: owner mismatch", __func__);
2527 if (0 != memcmp(&doxm1->rownerID, &doxm2->rownerID, sizeof(doxm1->rownerID)))
2529 OIC_LOG_V(ERROR, TAG, "%s: rownerID mismatch", __func__);
2533 #ifdef MULTIPLE_OWNER
2534 return AreDoxmBinMOTPropertyValuesEqual(doxm1, doxm2);
2540 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2541 OCStackResult EnableAnonCipherSuiteIfUnOwnedAndJustWorksSelected(bool *enabled)
2543 OCStackResult ret = OC_STACK_ERROR;
2545 OIC_LOG_V(INFO, TAG, "%s: function enter.", __func__);
2547 // If device unowned, check if JW OTM is selected.
2548 // If so, register handshake callback, and enable Anon Ciphersuite.
2549 if (NULL != gDoxm) {
2550 if (false == gDoxm->owned) {
2551 if (OIC_JUST_WORKS == gDoxm->oxmSel) {
2552 RegisterOTMSslHandshakeCallback(DoxmDTLSHandshakeCB);
2553 OIC_LOG_V(INFO, TAG, "%s: enabling AnonECDHCipherSuite", __func__);
2554 ret = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
2555 if (OC_STACK_OK == ret)
2557 OIC_LOG_V(INFO, TAG, "%s: AnonECDHCipherSuite ENABLED.", __func__);
2558 if (NULL != enabled)
2565 OIC_LOG_V(ERROR, TAG, "%s: Error attempting to enable AnonECDHCipherSuite!", __func__);
2570 OIC_LOG_V(INFO, TAG, "%s: JustWorks not selected; NOT enabling AnonECDHCipherSuite.", __func__);
2576 OIC_LOG_V(INFO, TAG, "%s: Device is owned; NOT enabling AnonECDHCipherSuite.", __func__);
2582 OIC_LOG_V(INFO, TAG, "%s: gDoxm is NULL; NOT enabling AnonECDHCipherSuite.", __func__);
2586 if (NULL != enabled)
2588 if (true != *enabled)
2594 OIC_LOG_V(INFO, TAG, "%s: function exit, returning %s.", __func__,
2595 (OC_STACK_OK == ret) ? "OC_STACK_OK" : "OC_STACK_ERROR");
2599 #endif // __WITH_DTLS__ or __WITH_TLS__