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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
25 #include "oic_malloc.h"
26 #include "ocpayload.h"
27 #include "ocpayloadcbor.h"
28 #include "payload_logging.h"
29 #include "resourcemanager.h"
30 #include "pstatresource.h"
31 #include "doxmresource.h"
32 #include "psinterface.h"
33 #include "srmresourcestrings.h"
34 #include "srmutility.h"
36 #define TAG "OIC_SRM_PSTAT"
38 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
39 * The value of payload size is increased until reaching below max cbor size. */
40 static const uint16_t CBOR_SIZE = 512;
42 // Max cbor size payload.
43 static const uint16_t CBOR_MAX_SIZE = 4400;
45 // PSTAT Map size - Number of mandatory items
46 static const uint8_t PSTAT_MAP_SIZE = 6;
48 // Number of writeable property
49 static const uint8_t WRITEABLE_PROPERTY_SIZE = 3;
51 static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
52 static OicSecPstat_t gDefaultPstat =
55 (OicSecDpm_t)(BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
56 PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t cm
57 (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
58 PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t tm
59 {.id = {0}}, // OicUuid_t deviceID
60 SINGLE_SERVICE_CLIENT_DRIVEN, // OicSecDpom_t om */
61 1, // the number of elts in Sms
62 &gSm, // OicSecDpom_t *sm
63 0, // uint16_t commitHash
64 {.id = {0}}, // OicUuid_t rownerID
67 static OicSecPstat_t *gPstat = NULL;
69 static OCResourceHandle gPstatHandle = NULL;
72 * This method is internal method.
73 * the param roParsed is optionally used to know whether cborPayload has
74 * at least read only property value or not.
76 static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const size_t size,
77 OicSecPstat_t **secPstat, bool *roParsed);
79 void DeletePstatBinData(OicSecPstat_t* pstat)
83 //Clean 'supported modes' field
91 OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size,
94 if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size)
96 return OC_STACK_INVALID_PARAM;
99 size_t cborLen = *size;
108 OCStackResult ret = OC_STACK_ERROR;
109 size_t pstatMapSize = PSTAT_MAP_SIZE;
111 CborEncoder pstatMap;
112 char* strUuid = NULL;
114 int64_t cborEncoderResult = CborNoError;
116 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
117 VERIFY_NON_NULL(TAG, outPayload, ERROR);
118 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
120 if (false == writableOnly)
122 pstatMapSize += WRITEABLE_PROPERTY_SIZE;
125 cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, pstatMapSize);
126 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
128 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME,
129 strlen(OIC_JSON_ISOP_NAME));
130 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag.");
131 cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp);
132 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value.");
134 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME,
135 strlen(OIC_JSON_CM_NAME));
136 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag.");
137 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm);
138 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value.");
140 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME,
141 strlen(OIC_JSON_TM_NAME));
142 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag.");
143 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm);
144 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value.");
146 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME,
147 strlen(OIC_JSON_OM_NAME));
148 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag.");
149 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om);
150 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value.");
152 if (false == writableOnly)
154 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME,
155 strlen(OIC_JSON_SM_NAME));
156 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag.");
157 cborEncoderResult = cbor_encode_int(&pstatMap, pstat->sm[0]);
158 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Value.");
160 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME,
161 strlen(OIC_JSON_DEVICE_ID_NAME));
162 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
163 ret = ConvertUuidToStr(&pstat->deviceID, &strUuid);
164 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
165 cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
166 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
170 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ROWNERID_NAME,
171 strlen(OIC_JSON_ROWNERID_NAME));
172 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
173 ret = ConvertUuidToStr(&pstat->rownerID, &strUuid);
174 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
175 cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
176 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
183 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_RT_NAME,
184 strlen(OIC_JSON_RT_NAME));
185 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
186 cborEncoderResult = cbor_encoder_create_array(&pstatMap, &rtArray, 1);
187 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
188 for (size_t i = 0; i < 1; i++)
190 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_PSTAT,
191 strlen(OIC_RSRC_TYPE_SEC_PSTAT));
192 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
194 cborEncoderResult = cbor_encoder_close_container(&pstatMap, &rtArray);
195 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
199 cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_IF_NAME,
200 strlen(OIC_JSON_IF_NAME));
201 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
202 cborEncoderResult = cbor_encoder_create_array(&pstatMap, &ifArray, 1);
203 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
204 for (size_t i = 0; i < 1; i++)
206 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
207 strlen(OC_RSRVD_INTERFACE_DEFAULT));
208 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
210 cborEncoderResult = cbor_encoder_close_container(&pstatMap, &ifArray);
211 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
213 cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap);
214 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map.");
216 if (CborNoError == cborEncoderResult)
218 *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
219 *payload = outPayload;
223 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
225 // reallocate and try again!
228 // Since the allocated initial memory failed, double the memory.
229 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
230 cborEncoderResult = CborNoError;
231 ret = PstatToCBORPayload(pstat, payload, &cborLen, writableOnly);
232 if (OC_STACK_OK == ret)
238 if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
244 ret = OC_STACK_ERROR;
250 OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size,
251 OicSecPstat_t **secPstat)
253 return CBORPayloadToPstatBin(cborPayload, size, secPstat, NULL);
256 static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload, const size_t size,
257 OicSecPstat_t **secPstat, bool *roParsed)
259 if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat || 0 == size)
261 return OC_STACK_INVALID_PARAM;
264 OCStackResult ret = OC_STACK_ERROR;
269 CborError cborFindResult = CborNoError;
270 char *strUuid = NULL;
273 cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor);
274 CborValue pstatMap = { .parser = NULL };
276 OicSecPstat_t *pstat = NULL;
277 cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
278 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map.");
280 pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
281 VERIFY_NON_NULL(TAG, pstat, ERROR);
283 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap);
284 if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap))
286 cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp);
287 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value.");
291 pstat->isOp = gPstat->isOp;
292 cborFindResult = CborNoError;
295 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DEVICE_ID_NAME, &pstatMap);
296 if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
298 cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
299 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
300 ret = ConvertStrToUuid(strUuid , &pstat->deviceID);
301 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
308 memcpy(&pstat->deviceID, &gPstat->deviceID, sizeof(OicUuid_t));
309 cborFindResult = CborNoError;
312 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_CM_NAME, &pstatMap);
313 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
317 cborFindResult = cbor_value_get_int(&pstatMap, &cm);
318 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM.");
319 pstat->cm = (OicSecDpm_t)cm;
323 pstat->cm = gPstat->cm;
324 cborFindResult = CborNoError;
327 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap);
328 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
332 cborFindResult = cbor_value_get_int(&pstatMap, &tm);
333 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM.");
334 pstat->tm = (OicSecDpm_t)tm;
338 pstat->tm = gPstat->tm;
339 cborFindResult = CborNoError;
342 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_OM_NAME, &pstatMap);
343 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
347 cborFindResult = cbor_value_get_int(&pstatMap, &om);
348 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM.");
349 pstat->om = (OicSecDpom_t)om;
353 pstat->om = gPstat->om;
354 cborFindResult = CborNoError;
357 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap);
358 if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
363 pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
364 VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
365 cborFindResult = cbor_value_get_int(&pstatMap, &sm);
366 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM.");
367 pstat->sm[0] = (OicSecDpom_t)sm;
376 VERIFY_NON_NULL(TAG, gPstat, ERROR);
377 pstat->smLen = gPstat->smLen;
378 pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
379 VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
380 *pstat->sm = *gPstat->sm;
381 cborFindResult = CborNoError;
384 cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ROWNERID_NAME, &pstatMap);
385 if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
387 cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
388 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Id Value.");
389 ret = ConvertStrToUuid(strUuid , &pstat->rownerID);
390 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
396 VERIFY_NON_NULL(TAG, gPstat, ERROR);
397 memcpy(pstat->rownerID.id, gPstat->rownerID.id, sizeof(gPstat->rownerID.id));
398 cborFindResult = CborNoError;
405 if (CborNoError != cborFindResult)
407 OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed");
408 DeletePstatBinData(pstat);
411 ret = OC_STACK_ERROR;
418 * Function to update persistent storage
420 static bool UpdatePersistentStorage(OicSecPstat_t *pstat)
425 uint8_t *cborPayload = NULL;
426 OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size, false);
427 if (OC_STACK_OK == ret)
429 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
433 OICFree(cborPayload);
439 static bool ValidateQuery(const char * query)
441 OIC_LOG (DEBUG, TAG, "In ValidateQuery");
447 bool bInterfaceQry = false; // does querystring contains 'if' query ?
448 bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
450 OicParseQueryIter_t parseIter = {.attrPos = NULL};
452 ParseQueryIterInit((unsigned char*)query, &parseIter);
454 while (GetNextQuery(&parseIter))
456 if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
458 bInterfaceQry = true;
459 if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
461 bInterfaceMatch = true;
465 return (bInterfaceQry ? bInterfaceMatch: true);
468 #ifdef MULTIPLE_OWNER
469 bool IsValidPstatAccessForSubOwner(const uint8_t *cborPayload, size_t size)
471 OicSecPstat_t* pstat = NULL;
472 bool isValidPstat = true;
474 OIC_LOG_BUFFER(DEBUG, TAG, cborPayload, size);
475 VERIFY_NON_NULL(TAG, cborPayload, ERROR);
476 VERIFY_SUCCESS(TAG, 0 != size, ERROR);
477 VERIFY_SUCCESS(TAG, OC_STACK_OK == CBORPayloadToPstat(cborPayload, size, &pstat), ERROR);
478 VERIFY_NON_NULL(TAG, pstat, ERROR);
480 if (RESET & pstat->cm)
482 OIC_LOG(ERROR, TAG, "SubOwner can't reset the server.");
483 isValidPstat = false;
487 DeletePstatBinData(pstat);
490 #endif //MULTIPLE_OWNER
493 * The entity handler determines how to process a GET request.
495 static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
497 OCEntityHandlerResult ehRet = OC_EH_OK;
499 OIC_LOG(INFO, TAG, "HandlePstatGetRequest processing GET request");
501 //Checking if Get request is a query.
502 if (ehRequest->query)
504 OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
505 OIC_LOG(DEBUG, TAG, "HandlePstatGetRequest processing query");
506 if (!ValidateQuery(ehRequest->query))
513 * For GET or Valid Query request return doxm resource CBOR payload.
514 * For non-valid query return NULL json payload.
515 * A device will 'always' have a default Pstat, so PstatToCBORPayload will
516 * return valid pstat resource json.
519 uint8_t *payload = NULL;
520 if (ehRet == OC_EH_OK)
522 if(OC_STACK_OK != PstatToCBORPayload(gPstat, &payload, &size, false))
524 OIC_LOG(WARNING, TAG, "PstatToCBORPayload failed in HandlePstatGetRequest");
528 // Send response payload to request originator
529 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
530 OC_EH_OK : OC_EH_ERROR;
536 * The entity handler determines how to process a POST request.
537 * Per the REST paradigm, POST can also be used to update representation of existing
538 * resource or create a new resource.
539 * For pstat, it updates only tm and om.
541 static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRequest)
543 OCEntityHandlerResult ehRet = OC_EH_ERROR;
544 OIC_LOG(INFO, TAG, "HandlePstatPostRequest processing POST request");
545 OicSecPstat_t *pstat = NULL;
546 static uint16_t previousMsgId = 0;
547 bool isDuplicatedMsg = false;
549 if (ehRequest->payload && NULL != gPstat)
551 uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
552 size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
553 VERIFY_NON_NULL(TAG, payload, ERROR);
555 bool roParsed = false;
556 OCStackResult ret = CBORPayloadToPstatBin(payload, size, &pstat, &roParsed);
557 VERIFY_NON_NULL(TAG, pstat, ERROR);
558 if (OC_STACK_OK == ret)
560 bool validReq = false;
563 * message ID is supported for CoAP over UDP only according to RFC 7252
564 * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
565 * In case of other transport adapter, duplicate message check is not required.
567 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
568 previousMsgId == ehRequest->messageID)
570 isDuplicatedMsg = true;
573 if (true == roParsed)
575 OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
576 ehRet = OC_EH_NOT_ACCEPTABLE;
580 //operation mode(om) should be one of supported modes(sm)
581 for(size_t i = 0; i < gPstat->smLen; i++)
583 if(gPstat->sm[i] == pstat->om)
592 OIC_LOG_V(ERROR, TAG, "%d is unsupported Operation Mode", (int) pstat->om);
593 ehRet = OC_EH_BAD_REQ;
598 //Currently, IoTivity only supports Single Service Client Directed provisioning
599 if (pstat->om == SINGLE_SERVICE_CLIENT_DRIVEN)
601 if ((pstat->cm & RESET) && false == pstat->isOp)
604 OIC_LOG(INFO, TAG, "State changed to Ready for Reset");
606 else if ((pstat->cm & TAKE_OWNER) && false == pstat->isOp)
609 OIC_LOG (INFO, TAG, "State changed to Ready for Ownership transfer");
611 else if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
614 OIC_LOG(INFO, TAG, "State changed to Ready for Provisioning");
616 else if (false == (pstat->cm & TAKE_OWNER) && true == pstat->isOp)
619 OIC_LOG (INFO, TAG, "State changed to Ready for Normal Operation");
623 OIC_LOG(DEBUG, TAG, "Invalid Device provisionig state");
624 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
625 ehRet = OC_EH_BAD_REQ;
632 OIC_LOG(DEBUG, TAG, "Bad request for PSTAT");
633 ehRet = OC_EH_BAD_REQ;
637 gPstat->isOp = pstat->isOp;
638 gPstat->om = pstat->om;
639 gPstat->tm = pstat->tm;
640 gPstat->cm = pstat->cm;
641 memcpy(&(gPstat->deviceID), &(pstat->deviceID), sizeof(OicUuid_t));
642 memcpy(&(gPstat->rownerID), &(pstat->rownerID), sizeof(OicUuid_t));
644 // Convert pstat data into CBOR for update to persistent storage
645 if (UpdatePersistentStorage(gPstat))
649 if (true == (pstat->cm & RESET))
651 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
654 OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
655 DeletePstatBinData(pstat);
658 ret = ResetSecureResourceInPS();
659 if (OC_STACK_OK == ret)
663 DeletePstatBinData(pstat);
670 if(OC_EH_OK != ehRet)
673 * If some error is occured while ownership transfer,
674 * ownership transfer related resource should be revert back to initial status.
676 const OicSecDoxm_t* doxm = GetDoxmResourceData();
681 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
683 if (!isDuplicatedMsg)
685 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
686 InvokeOtmEventHandler(ehRequest->devAddr.addr, ehRequest->devAddr.port,
687 NULL, OIC_OTM_ERROR);
689 RestoreDoxmToInitState();
690 RestorePstatToInitState();
691 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
697 OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
702 if(ehRequest->devAddr.adapter == OC_ADAPTER_IP)
704 previousMsgId = ehRequest->messageID;
708 // Send response payload to request originator
709 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
710 OC_EH_OK : OC_EH_ERROR;
712 DeletePstatBinData(pstat);
717 * This internal method is the entity handler for pstat resources.
719 OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
720 OCEntityHandlerRequest * ehRequest,
724 OCEntityHandlerResult ehRet = OC_EH_ERROR;
725 // This method will handle REST request (GET/POST) for /oic/sec/pstat
726 if (flag & OC_REQUEST_FLAG)
728 OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
729 switch (ehRequest->method)
732 ehRet = HandlePstatGetRequest(ehRequest);
735 ehRet = HandlePstatPostRequest(ehRequest);
738 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
739 OC_EH_OK : OC_EH_ERROR;
747 * This internal method is used to create '/oic/sec/pstat' resource.
749 OCStackResult CreatePstatResource()
751 OCStackResult ret = OCCreateResource(&gPstatHandle,
752 OIC_RSRC_TYPE_SEC_PSTAT,
753 OC_RSRVD_INTERFACE_DEFAULT,
760 if (OC_STACK_OK != ret)
762 OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource");
763 DeInitPstatResource();
769 * Get the default value.
771 * @return the gDefaultPstat pointer.
773 static OicSecPstat_t* GetPstatDefault()
775 return &gDefaultPstat;
778 OCStackResult InitPstatResource()
780 OCStackResult ret = OC_STACK_ERROR;
782 // Read Pstat resource from PS
783 uint8_t *data = NULL;
785 OicUuid_t emptyUuid = {.id={0}};
786 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size);
787 // If database read failed
788 if (OC_STACK_OK != ret)
790 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
794 // Read ACL resource from PS
795 ret = CBORPayloadToPstat(data, size, &gPstat);
799 * If SVR database in persistent storage got corrupted or
800 * is not available for some reason, a default pstat is created
801 * which allows user to initiate pstat provisioning again.
803 if ((OC_STACK_OK != ret) || !gPstat)
805 gPstat = GetPstatDefault();
807 VERIFY_NON_NULL(TAG, gPstat, FATAL);
809 //In case of Pstat's device id is empty, fill the device id as doxm's device id.
810 if(0 == memcmp(&gPstat->deviceID, &emptyUuid, sizeof(OicUuid_t)))
812 OicUuid_t doxmUuid = {.id={0}};
813 if(OC_STACK_OK == GetDoxmDeviceID(&doxmUuid))
815 memcpy(&gPstat->deviceID, &doxmUuid, sizeof(OicUuid_t));
819 // Instantiate 'oic.sec.pstat'
820 ret = CreatePstatResource();
823 if (OC_STACK_OK != ret)
825 DeInitPstatResource();
830 OCStackResult DeInitPstatResource()
832 if (gPstat != &gDefaultPstat)
834 DeletePstatBinData(gPstat);
837 return OCDeleteResource(gPstatHandle);
841 * Function to restore pstat resurce to initial status.
842 * This function will use in case of error while ownership transfer
844 void RestorePstatToInitState()
848 OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
850 gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER);
851 gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER));
852 gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
853 if(gPstat->sm && 0 < gPstat->smLen)
855 gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
858 if (!UpdatePersistentStorage(gPstat))
860 OIC_LOG(ERROR, TAG, "Failed to revert PSTAT in persistent storage");
865 OCStackResult SetPstatRownerId(const OicUuid_t* newROwner)
867 OCStackResult ret = OC_STACK_ERROR;
868 uint8_t *cborPayload = NULL;
870 OicUuid_t prevId = {.id={0}};
872 if(NULL == newROwner)
874 ret = OC_STACK_INVALID_PARAM;
878 ret = OC_STACK_NO_RESOURCE;
881 if(newROwner && gPstat)
883 memcpy(prevId.id, gPstat->rownerID.id, sizeof(prevId.id));
884 memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id));
886 ret = PstatToCBORPayload(gPstat, &cborPayload, &size, false);
887 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
889 ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size);
890 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
892 OICFree(cborPayload);
898 OICFree(cborPayload);
899 memcpy(gPstat->rownerID.id, prevId.id, sizeof(prevId.id));
904 * This function returns the "isop" status of the device.
906 * @return true iff pstat.isop == 1, else false
916 //In case of gPstat is NULL
921 OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid)
923 OCStackResult retVal = OC_STACK_ERROR;
926 *rowneruuid = gPstat->rownerID;
927 retVal = OC_STACK_OK;
932 OCStackResult SetPstatSelfOwnership(const OicUuid_t* newROwner)
934 OCStackResult ret = OC_STACK_ERROR;
935 uint8_t *cborPayload = NULL;
940 ret = OC_STACK_NO_RESOURCE;
944 if( newROwner && (false == gPstat->isOp) && (true == (TAKE_OWNER && gPstat->cm)) )
946 gPstat->cm = (OicSecDpm_t)(gPstat->cm & (~TAKE_OWNER));
949 memcpy(gPstat->deviceID.id, newROwner->id, sizeof(newROwner->id));
950 memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id));
952 ret = PstatToCBORPayload(gPstat, &cborPayload, &size, false);
953 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
955 ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size);
956 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
958 OICFree(cborPayload);
962 OIC_LOG(ERROR, TAG, "The state of PSTAT is not Ready For OTM");
968 OICFree(cborPayload);