Merge branch '1.1-rel'
[platform/upstream/iotivity.git] / resource / csdk / security / src / pstatresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "ocstack.h"
25 #include "oic_malloc.h"
26 #include "ocpayload.h"
27 #include "payload_logging.h"
28 #include "resourcemanager.h"
29 #include "pstatresource.h"
30 #include "doxmresource.h"
31 #include "psinterface.h"
32 #include "srmresourcestrings.h"
33 #include "srmutility.h"
34
35 #define TAG  "SRM-PSTAT"
36
37 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
38  * The value of payload size is increased until reaching below max cbor size. */
39 static const uint16_t CBOR_SIZE = 512;
40
41 // Max cbor size payload.
42 static const uint16_t CBOR_MAX_SIZE = 4400;
43
44 // PSTAT Map size - Number of mandatory items
45 static const uint8_t PSTAT_MAP_SIZE = 7;
46
47 static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
48 static OicSecPstat_t gDefaultPstat =
49 {
50     false,                                    // bool isop
51     (OicSecDpm_t)(BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
52     PROVISION_CREDENTIALS | PROVISION_ACLS),   // OicSecDpm_t cm
53     (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
54     PROVISION_CREDENTIALS | PROVISION_ACLS),   // OicSecDpm_t tm
55     {.id = {0}},                              // OicUuid_t deviceID
56     SINGLE_SERVICE_CLIENT_DRIVEN,             // OicSecDpom_t om */
57     1,                                        // the number of elts in Sms
58     &gSm,                                     // OicSecDpom_t *sm
59     0,                                        // uint16_t commitHash
60     {.id = {0}},                              // OicUuid_t rownerID
61 };
62
63 static OicSecPstat_t    *gPstat = NULL;
64
65 static OCResourceHandle gPstatHandle = NULL;
66
67 void DeletePstatBinData(OicSecPstat_t* pstat)
68 {
69     if (pstat)
70     {
71         //Clean 'supported modes' field
72         OICFree(pstat->sm);
73
74         //Clean pstat itself
75         OICFree(pstat);
76     }
77 }
78
79 OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat, uint8_t **payload, size_t *size)
80 {
81     if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size)
82     {
83         return OC_STACK_INVALID_PARAM;
84     }
85
86     size_t cborLen = *size;
87     if (0 == cborLen)
88     {
89         cborLen = CBOR_SIZE;
90     }
91
92     *payload = NULL;
93     *size = 0;
94
95     OCStackResult ret = OC_STACK_ERROR;
96
97     CborEncoder encoder;
98     CborEncoder pstatMap;
99     char* strUuid = NULL;
100
101     int64_t cborEncoderResult = CborNoError;
102
103     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
104     VERIFY_NON_NULL(TAG, outPayload, ERROR);
105     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
106
107     cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, PSTAT_MAP_SIZE);
108     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
109
110     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME,
111         strlen(OIC_JSON_ISOP_NAME));
112     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag.");
113     cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp);
114     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value.");
115
116     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DEVICE_ID_NAME,
117         strlen(OIC_JSON_DEVICE_ID_NAME));
118     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Tag.");
119     ret = ConvertUuidToStr(&pstat->deviceID, &strUuid);
120     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
121     cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
122     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Id Value.");
123     OICFree(strUuid);
124     strUuid = NULL;
125
126     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME,
127         strlen(OIC_JSON_CM_NAME));
128     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag.");
129     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm);
130     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value.");
131
132     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME,
133         strlen(OIC_JSON_TM_NAME));
134     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag.");
135     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm);
136     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value.");
137
138     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME,
139         strlen(OIC_JSON_OM_NAME));
140     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag.");
141     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om);
142     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value.");
143
144     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME,
145         strlen(OIC_JSON_SM_NAME));
146     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag.");
147     cborEncoderResult = cbor_encode_int(&pstatMap, pstat->sm[0]);
148     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Value.");
149
150     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ROWNERID_NAME,
151         strlen(OIC_JSON_ROWNERID_NAME));
152     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
153     ret = ConvertUuidToStr(&pstat->rownerID, &strUuid);
154     VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
155     cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
156     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
157     OICFree(strUuid);
158     strUuid = NULL;
159
160     cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap);
161     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map.");
162
163     if (CborNoError == cborEncoderResult)
164     {
165         *size = encoder.ptr - outPayload;
166         *payload = outPayload;
167         ret = OC_STACK_OK;
168     }
169 exit:
170     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
171     {
172         // reallocate and try again!
173         OICFree(outPayload);
174         // Since the allocated initial memory failed, double the memory.
175         cborLen += encoder.ptr - encoder.end;
176         cborEncoderResult = CborNoError;
177         ret = PstatToCBORPayload(pstat, payload, &cborLen);
178         if (OC_STACK_OK == ret)
179         {
180             *size = cborLen;
181         }
182     }
183
184     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
185     {
186         OICFree(outPayload);
187         outPayload = NULL;
188         *payload = NULL;
189         *size = 0;
190         ret = OC_STACK_ERROR;
191     }
192
193     return ret;
194 }
195
196 OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size,
197                                  OicSecPstat_t **secPstat)
198 {
199     if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat || 0 == size)
200     {
201         return OC_STACK_INVALID_PARAM;
202     }
203
204     OCStackResult ret = OC_STACK_ERROR;
205     *secPstat = NULL;
206
207     CborValue pstatCbor;
208     CborParser parser;
209     CborError cborFindResult = CborNoError;
210     char *strUuid = NULL;
211     size_t len = 0;
212
213     cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor);
214     CborValue pstatMap = { .parser = NULL };
215
216     OicSecPstat_t *pstat = NULL;
217     cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
218     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Map.");
219
220     pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
221     VERIFY_NON_NULL(TAG, pstat, ERROR);
222
223     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap);
224     if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap))
225     {
226         cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp);
227         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value.");
228     }
229
230     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DEVICE_ID_NAME, &pstatMap);
231     if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
232     {
233         cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
234         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Id Value.");
235         ret = ConvertStrToUuid(strUuid , &pstat->deviceID);
236         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
237         OICFree(strUuid );
238         strUuid  = NULL;
239     }
240
241     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_CM_NAME, &pstatMap);
242     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
243     {
244         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->cm);
245         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM.");
246     }
247
248     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap);
249     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
250     {
251         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->tm);
252         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM.");
253     }
254
255     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_OM_NAME, &pstatMap);
256     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
257     {
258         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->om);
259         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM.");
260     }
261
262     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap);
263     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
264     {
265         pstat->smLen = 1;
266         pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
267         cborFindResult = cbor_value_get_int(&pstatMap, (int *) &pstat->sm[0]);
268         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM.");
269
270     }
271
272     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ROWNERID_NAME, &pstatMap);
273     if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
274     {
275         cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
276         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Id Value.");
277         ret = ConvertStrToUuid(strUuid , &pstat->rownerID);
278         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
279         OICFree(strUuid );
280         strUuid  = NULL;
281     }
282
283     *secPstat = pstat;
284     ret = OC_STACK_OK;
285
286 exit:
287     if (CborNoError != cborFindResult)
288     {
289         OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed");
290         DeletePstatBinData(pstat);
291         pstat = NULL;
292         *secPstat = NULL;
293         ret = OC_STACK_ERROR;
294     }
295
296     return ret;
297 }
298
299 /**
300  * Function to update persistent storage
301  */
302 static bool UpdatePersistentStorage(OicSecPstat_t *pstat)
303 {
304     bool bRet = false;
305
306     size_t size = 0;
307     uint8_t *cborPayload = NULL;
308     OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size);
309     if (OC_STACK_OK == ret)
310     {
311         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
312         {
313             bRet = true;
314         }
315         OICFree(cborPayload);
316     }
317
318     return bRet;
319 }
320
321
322 /**
323  * The entity handler determines how to process a GET request.
324  */
325 static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
326 {
327     OIC_LOG(INFO, TAG, "HandlePstatGetRequest  processing GET request");
328
329     // Convert ACL data into CBOR for transmission
330     size_t size = 0;
331     uint8_t *payload = NULL;
332     OCStackResult res = PstatToCBORPayload(gPstat, &payload, &size);
333
334     // A device should always have a default pstat. Therefore, payload should never be NULL.
335     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
336
337     // Send response payload to request originator
338     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
339     {
340         ehRet = OC_EH_ERROR;
341         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatGetRequest");
342     }
343     OICFree(payload);
344     return ehRet;
345 }
346
347 /**
348  * The entity handler determines how to process a POST request.
349  * Per the REST paradigm, POST can also be used to update representation of existing
350  * resource or create a new resource.
351  * For pstat, it updates only tm and om.
352  */
353 static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest *ehRequest)
354 {
355     OCEntityHandlerResult ehRet = OC_EH_ERROR;
356     OIC_LOG(INFO, TAG, "HandlePstatPutRequest  processing PUT request");
357     OicSecPstat_t *pstat = NULL;
358
359     if (ehRequest->payload)
360     {
361         uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
362         size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
363         VERIFY_NON_NULL(TAG, payload, ERROR);
364
365         OCStackResult ret = CBORPayloadToPstat(payload, size, &pstat);
366         VERIFY_NON_NULL(TAG, pstat, ERROR);
367         if (OC_STACK_OK == ret)
368         {
369             if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
370             {
371                 gPstat->cm = pstat->cm;
372                 OIC_LOG (INFO, TAG, "State changed to Ready for Provisioning");
373             }
374             else if (false == (pstat->cm & TAKE_OWNER) && true == pstat->isOp)
375             {
376                 gPstat->isOp =pstat->isOp;
377                 OIC_LOG (INFO, TAG, "State changed to Ready for Normal Operation");
378             }
379             else
380             {
381                 OIC_LOG(DEBUG, TAG, "Invalid Device provisionig state");
382             }
383             if (pstat->om != MULTIPLE_SERVICE_SERVER_DRIVEN && gPstat)
384             {
385                 /*
386                  * Check if the operation mode is in the supported provisioning services
387                  * operation mode list.
388                  */
389                 for (size_t i=0; i< gPstat->smLen; i++)
390                 {
391                     if(gPstat->sm[i] == pstat->om)
392                     {
393                         gPstat->om = pstat->om;
394                         break;
395                     }
396                 }
397             }
398             // Convert pstat data into CBOR for update to persistent storage
399             if (UpdatePersistentStorage(gPstat))
400             {
401                 ehRet = OC_EH_OK;
402             }
403         }
404     }
405  exit:
406     if(OC_EH_OK != ehRet)
407     {
408         /*
409           * If some error is occured while ownership transfer,
410           * ownership transfer related resource should be revert back to initial status.
411           */
412         RestoreDoxmToInitState();
413         RestorePstatToInitState();
414     }
415
416     //Send payload to request originator
417     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
418     {
419         ehRet = OC_EH_ERROR;
420         OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
421     }
422     DeletePstatBinData(pstat);
423     return ehRet;
424 }
425
426 /**
427  * This internal method is the entity handler for pstat resources.
428  */
429  OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
430                                           OCEntityHandlerRequest * ehRequest,
431                                           void *callbackParam)
432 {
433     (void)callbackParam;
434     OCEntityHandlerResult ehRet = OC_EH_ERROR;
435     // This method will handle REST request (GET/POST) for /oic/sec/pstat
436     if (flag & OC_REQUEST_FLAG)
437     {
438         OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
439         switch (ehRequest->method)
440         {
441             case OC_REST_GET:
442                 ehRet = HandlePstatGetRequest(ehRequest);
443                 break;
444             case OC_REST_PUT:
445                 ehRet = HandlePstatPutRequest(ehRequest);
446                 break;
447             default:
448                 ehRet = OC_EH_ERROR;
449                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
450                 break;
451         }
452     }
453     return ehRet;
454 }
455
456 /**
457  * This internal method is used to create '/oic/sec/pstat' resource.
458  */
459  OCStackResult CreatePstatResource()
460 {
461     OCStackResult ret = OCCreateResource(&gPstatHandle,
462                                          OIC_RSRC_TYPE_SEC_PSTAT,
463                                          OIC_MI_DEF,
464                                          OIC_RSRC_PSTAT_URI,
465                                          PstatEntityHandler,
466                                          NULL,
467                                          OC_RES_PROP_NONE);
468
469     if (OC_STACK_OK != ret)
470     {
471         OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource");
472         DeInitPstatResource();
473     }
474     return ret;
475 }
476
477 /**
478  * Get the default value.
479  *
480  * @return the gDefaultPstat pointer.
481  */
482 static OicSecPstat_t* GetPstatDefault()
483 {
484     return &gDefaultPstat;
485 }
486
487 OCStackResult InitPstatResource()
488 {
489     OCStackResult ret = OC_STACK_ERROR;
490
491     // Read Pstat resource from PS
492     uint8_t *data = NULL;
493     size_t size = 0;
494     OicUuid_t emptyUuid = {.id={0}};
495     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size);
496     // If database read failed
497     if (OC_STACK_OK != ret)
498     {
499         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
500     }
501     if (data)
502     {
503         // Read ACL resource from PS
504         ret = CBORPayloadToPstat(data, size, &gPstat);
505         OICFree(data);
506     }
507     /*
508      * If SVR database in persistent storage got corrupted or
509      * is not available for some reason, a default pstat is created
510      * which allows user to initiate pstat provisioning again.
511      */
512     if ((OC_STACK_OK != ret) || !gPstat)
513     {
514         gPstat = GetPstatDefault();
515     }
516     VERIFY_NON_NULL(TAG, gPstat, FATAL);
517
518     //In case of Pstat's device id is empty, fill the device id as doxm's device id.
519     if(0 == memcmp(&gPstat->deviceID, &emptyUuid, sizeof(OicUuid_t)))
520     {
521         OicUuid_t doxmUuid = {.id={0}};
522         if(OC_STACK_OK == GetDoxmDeviceID(&doxmUuid))
523         {
524             memcpy(&gPstat->deviceID, &doxmUuid, sizeof(OicUuid_t));
525         }
526     }
527
528     // Instantiate 'oic.sec.pstat'
529     ret = CreatePstatResource();
530
531 exit:
532     if (OC_STACK_OK != ret)
533     {
534         DeInitPstatResource();
535     }
536     return ret;
537 }
538
539 OCStackResult DeInitPstatResource()
540 {
541     if (gPstat != &gDefaultPstat)
542     {
543         DeletePstatBinData(gPstat);
544         gPstat = NULL;
545     }
546     return OCDeleteResource(gPstatHandle);
547 }
548
549 /**
550  * Function to restore pstat resurce to initial status.
551  * This function will use in case of error while ownership transfer
552  */
553 void RestorePstatToInitState()
554 {
555     if(gPstat)
556     {
557         OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
558
559         gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER);
560         gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER));
561         gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
562         if(gPstat->sm && 0 < gPstat->smLen)
563         {
564             gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
565         }
566
567         if (!UpdatePersistentStorage(gPstat))
568         {
569             OIC_LOG(ERROR, TAG, "Failed to revert PSTAT in persistent storage");
570         }
571     }
572 }
573
574 OCStackResult SetPstatRownerId(const OicUuid_t* newROwner)
575 {
576     OCStackResult ret = OC_STACK_ERROR;
577     uint8_t *cborPayload = NULL;
578     size_t size = 0;
579     OicUuid_t prevId = {.id={0}};
580
581     if(NULL == newROwner)
582     {
583         ret = OC_STACK_INVALID_PARAM;
584     }
585     if(NULL == gPstat)
586     {
587         ret = OC_STACK_NO_RESOURCE;
588     }
589
590     if(newROwner && gPstat)
591     {
592         memcpy(prevId.id, gPstat->rownerID.id, sizeof(prevId.id));
593         memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id));
594
595         ret = PstatToCBORPayload(gPstat, &cborPayload, &size);
596         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
597
598         ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size);
599         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
600
601         OICFree(cborPayload);
602     }
603
604     return ret;
605
606 exit:
607     OICFree(cborPayload);
608     memcpy(gPstat->rownerID.id, prevId.id, sizeof(prevId.id));
609     return ret;
610 }
611
612 /**
613  * This function returns the "isop" status of the device.
614  *
615  * @return true iff pstat.isop == 1, else false
616  */
617 bool GetPstatIsop()
618 {
619     return gPstat->isOp;
620 }
621
622 OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid)
623 {
624     OCStackResult retVal = OC_STACK_ERROR;
625     if (gPstat)
626     {
627         *rowneruuid = gPstat->rownerID;
628         retVal = OC_STACK_OK;
629     }
630     return retVal;
631 }