01ae91c4fc578a78dcc58c2d2a20432853083923
[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 "iotivity_config.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "ocstack.h"
27 #include "oic_malloc.h"
28 #include "ocpayload.h"
29 #include "ocpayloadcbor.h"
30 #include "payload_logging.h"
31 #include "resourcemanager.h"
32 #include "pstatresource.h"
33 #include "doxmresource.h"
34 #include "psinterface.h"
35 #include "srmresourcestrings.h"
36 #include "srmutility.h"
37 #include "deviceonboardingstate.h"
38
39 #define TAG  "OIC_SRM_PSTAT"
40
41 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
42  * The value of payload size is increased until reaching below max cbor size. */
43 static const uint16_t CBOR_SIZE = 512;
44
45 // Max cbor size payload.
46 static const uint16_t CBOR_MAX_SIZE = 4400;
47
48 // starting pstat map size before adding any Properties, +2 for rt and if.
49 static const uint8_t PSTAT_EMPTY_MAP_SIZE = 2; // rt, if are included, in addition to props
50
51 // .dos Property map size
52 static const uint8_t PSTAT_DOS_MAP_SIZE = 2; // s, p
53
54 static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
55
56 static OicSecPstat_t gDefaultPstat =
57 {
58     {DOS_RFOTM, false},                       // OicSecDostype_t dos
59     false,                                    // bool isop
60     TAKE_OWNER,                               // OicSecDpm_t cm
61     NORMAL,                                   // OicSecDpm_t tm
62     SINGLE_SERVICE_CLIENT_DRIVEN,             // OicSecDpom_t om */
63     1,                                        // the number of elts in Sms
64     &gSm,                                     // OicSecDpom_t *sm
65     0,                                        // uint16_t commitHash
66     {.id = {0}},                              // OicUuid_t rowneruuid
67 };
68
69 static OicSecPstat_t    *gPstat = NULL;
70
71 static OCResourceHandle gPstatHandle = NULL;
72
73 #define R PERMISSION_READ
74 #define W PERMISSION_WRITE
75 #define RW PERMISSION_READ | PERMISSION_WRITE
76
77 static const uint8_t gPstatPropertyAccessModes[PSTAT_PROPERTY_COUNT][DOS_STATE_COUNT] =
78 { // RESET RFOTM  RFPRO   RFNOP   SRESET
79     { R,    RW,     RW,     RW,     RW  }, // .dos
80     { R,    R,      R,      R,      R   }, // .isop
81     { R,    R,      R,      R,      R   }, // .cm
82     { R,    RW,     RW,     RW,     RW  }, // .tm
83     { R,    RW,     RW,     RW,     RW  }, // .om
84     { R,    R,      R,      R,      R   }, // .sm
85     { R,    RW,     R,      R,      RW  }  // .rowneruuid
86 };
87
88 #undef R
89 #undef W
90 #undef RW
91
92 static bool IsPropertyReadOnly(PstatProperty_t p,
93                                OicSecDeviceOnboardingState_t s)
94 {
95     bool ret = false;
96
97     if (PERMISSION_READ == gPstatPropertyAccessModes[p][s])
98     {
99         OIC_LOG_V(DEBUG, TAG, "%s: property %d is read-only in state %d.",
100            __func__, p, s);
101         ret = true;
102     }
103
104     return ret;
105 }
106
107 /**
108  * Get the default value.
109  *
110  * @return the gDefaultPstat pointer.
111  */
112 static OicSecPstat_t* GetPstatDefault()
113 {
114     return &gDefaultPstat;
115 }
116
117 /**
118  * Internal method converts CBOR into PSTAT data, and determines if a read-only
119  *  Property was parsed in the CBOR payload.
120  *
121  * @param cborPayload The pstat data in cbor format.
122  * @param cborSize Size of the cborPayload. In case 0 is provided it assigns CBOR_SIZE (255) value.
123  * @param pstat Pointer to @ref OicSecPstat_t.
124  * @param roParsed Ptr to bool marked "true" iff a read-only Property is parsed
125  * @param stateForReadOnlyCheck The state to use when determining if a Property is
126  *                              read-only.
127  *
128  * @return ::OC_STACK_OK for Success, otherwise some error value.
129 */
130 static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload,
131                                            const size_t size,
132                                            OicSecPstat_t **secPstat,
133                                            bool *roParsed,
134                                            OicSecDeviceOnboardingState_t stateForReadOnlyCheck);
135
136
137 void DeletePstatBinData(OicSecPstat_t* pstat)
138 {
139     if (pstat)
140     {
141         //Clean 'supported modes' field
142         OICFree(pstat->sm);
143
144         //Clean pstat itself
145         OICFree(pstat);
146     }
147 }
148
149 /**
150  * Function to update persistent storage
151  */
152 static bool UpdatePersistentStorage(OicSecPstat_t *pstat)
153 {
154     bool bRet = false;
155
156     size_t size = 0;
157     uint8_t *cborPayload = NULL;
158     OCStackResult ret = PstatToCBORPayload(pstat, &cborPayload, &size);
159     if (OC_STACK_OK == ret)
160     {
161         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size))
162         {
163             bRet = true;
164         }
165         OICFree(cborPayload);
166     }
167
168     return bRet;
169 }
170
171 OCStackResult PstatToCBORPayloadPartial(const OicSecPstat_t *pstat,
172                                         uint8_t **payload,
173                                         size_t *size,
174                                         const bool *propertiesToInclude)
175 {
176     if (NULL == pstat || NULL == payload || NULL != *payload || NULL == size)
177     {
178         return OC_STACK_INVALID_PARAM;
179     }
180
181     size_t cborLen = *size;
182     if (0 == cborLen)
183     {
184         cborLen = CBOR_SIZE;
185     }
186
187     *payload = NULL;
188     *size = 0;
189
190     OCStackResult ret = OC_STACK_ERROR;
191     size_t pstatMapSize = PSTAT_EMPTY_MAP_SIZE;
192     CborEncoder encoder;
193     CborEncoder pstatMap;
194     char* strUuid = NULL;
195
196     int64_t cborEncoderResult = CborNoError;
197
198     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
199     VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
200
201     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
202
203     // Calculate map size
204     for (int i = 0; i < PSTAT_PROPERTY_COUNT; i++)
205     {
206         if (propertiesToInclude[i])
207         {
208             pstatMapSize++;
209         }
210     }
211     OIC_LOG_V(INFO, TAG, "%s: creating pstat CBOR payload with %d Properties.",
212         __func__, pstatMapSize - PSTAT_EMPTY_MAP_SIZE);
213
214     // Top Level Pstat Map
215     cborEncoderResult = cbor_encoder_create_map(&encoder, &pstatMap, pstatMapSize);
216     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pstat Map.");
217
218     // dos Property
219     if (propertiesToInclude[PSTAT_DOS])
220     {
221         OIC_LOG_V(DEBUG, TAG, "%s: including dos Property.", __func__);
222         // Device Onboarding State Property tag
223         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_DOS_NAME,
224             strlen(OIC_JSON_DOS_NAME));
225         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding dos Name Tag.");
226
227         // Device Onboarding State Property map
228         CborEncoder dosMap;
229         cborEncoderResult = cbor_encoder_create_map(&pstatMap, &dosMap, PSTAT_DOS_MAP_SIZE);
230         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed creating pstat.dos map");
231
232         cborEncoderResult = cbor_encode_text_string(&dosMap, OIC_JSON_S_NAME,
233             strlen(OIC_JSON_S_NAME));
234         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.s tag.");
235
236         cborEncoderResult = cbor_encode_int(&dosMap, pstat->dos.state);
237         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.s value.");
238
239         cborEncoderResult = cbor_encode_text_string(&dosMap, OIC_JSON_P_NAME,
240             strlen(OIC_JSON_P_NAME));
241         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.p tag.");
242
243         cborEncoderResult = cbor_encode_boolean(&dosMap, pstat->dos.pending);
244         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding pstat.dos.p value.");
245
246         cborEncoderResult = cbor_encoder_close_container(&pstatMap, &dosMap);
247         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing pstat.dos map");
248     }
249
250     // isop Property
251     if (propertiesToInclude[PSTAT_ISOP])
252     {
253         OIC_LOG_V(DEBUG, TAG, "%s: including isop Property.", __func__);
254         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ISOP_NAME,
255             strlen(OIC_JSON_ISOP_NAME));
256         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Tag.");
257         cborEncoderResult = cbor_encode_boolean(&pstatMap, pstat->isOp);
258         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ISOP Name Value.");
259     }
260
261     // cm Property
262     if (propertiesToInclude[PSTAT_CM])
263     {
264         OIC_LOG_V(DEBUG, TAG, "%s: including cm Property.", __func__);
265         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_CM_NAME,
266             strlen(OIC_JSON_CM_NAME));
267         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Tag.");
268         cborEncoderResult = cbor_encode_int(&pstatMap, pstat->cm);
269         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CM Name Value.");
270     }
271
272     // tm Property
273     if (propertiesToInclude[PSTAT_TM])
274     {
275         OIC_LOG_V(DEBUG, TAG, "%s: including tm Property.", __func__);
276         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_TM_NAME,
277             strlen(OIC_JSON_TM_NAME));
278         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Tag.");
279         cborEncoderResult = cbor_encode_int(&pstatMap, pstat->tm);
280         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding TM Name Value.");
281     }
282
283     // om Property
284     if (propertiesToInclude[PSTAT_OM])
285     {
286         OIC_LOG_V(DEBUG, TAG, "%s: including om Property.", __func__);
287         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_OM_NAME,
288             strlen(OIC_JSON_OM_NAME));
289         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Tag.");
290         cborEncoderResult = cbor_encode_int(&pstatMap, pstat->om);
291         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding OM Name Value.");
292     }
293
294     // sm Property
295     if (propertiesToInclude[PSTAT_SM])
296     {
297         OIC_LOG_V(DEBUG, TAG, "%s: including sm Property.", __func__);
298         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_SM_NAME,
299             strlen(OIC_JSON_SM_NAME));
300         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Tag.");
301         cborEncoderResult = cbor_encode_int(&pstatMap, pstat->sm[0]);
302         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SM Name Value.");
303     }
304
305     // rowneruuid property
306     if (propertiesToInclude[PSTAT_ROWNERUUID])
307     {
308         OIC_LOG_V(DEBUG, TAG, "%s: including rowneruuid Property.", __func__);
309         cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_ROWNERID_NAME,
310             strlen(OIC_JSON_ROWNERID_NAME));
311         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Tag.");
312         ret = ConvertUuidToStr(&pstat->rownerID, &strUuid);
313         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
314         cborEncoderResult = cbor_encode_text_string(&pstatMap, strUuid, strlen(strUuid));
315         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ROwner Id Value.");
316         OICFree(strUuid);
317         strUuid = NULL;
318     }
319
320     //RT -- Mandatory
321     CborEncoder rtArray;
322     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_RT_NAME,
323             strlen(OIC_JSON_RT_NAME));
324     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
325     cborEncoderResult = cbor_encoder_create_array(&pstatMap, &rtArray, 1);
326     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
327     for (size_t i = 0; i < 1; i++)
328     {
329         cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_PSTAT,
330                 strlen(OIC_RSRC_TYPE_SEC_PSTAT));
331         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
332     }
333     cborEncoderResult = cbor_encoder_close_container(&pstatMap, &rtArray);
334     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
335
336     //IF-- Mandatory
337     CborEncoder ifArray;
338     cborEncoderResult = cbor_encode_text_string(&pstatMap, OIC_JSON_IF_NAME,
339        strlen(OIC_JSON_IF_NAME));
340     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
341     cborEncoderResult = cbor_encoder_create_array(&pstatMap, &ifArray, 1);
342     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
343     for (size_t i = 0; i < 1; i++)
344     {
345         cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
346                 strlen(OC_RSRVD_INTERFACE_DEFAULT));
347         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
348     }
349     cborEncoderResult = cbor_encoder_close_container(&pstatMap, &ifArray);
350     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
351
352     cborEncoderResult = cbor_encoder_close_container(&encoder, &pstatMap);
353     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Closing PSTAT Map.");
354
355     if (CborNoError == cborEncoderResult)
356     {
357         *size = cbor_encoder_get_buffer_size(&encoder, outPayload);
358         *payload = outPayload;
359         ret = OC_STACK_OK;
360     }
361 exit:
362     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
363     {
364         // reallocate and try again!
365         OICFree(outPayload);
366         outPayload = NULL;
367         // Since the allocated initial memory failed, double the memory.
368         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
369         cborEncoderResult = CborNoError;
370         ret = PstatToCBORPayloadPartial(pstat, payload, &cborLen, propertiesToInclude);
371         if (OC_STACK_OK == ret)
372         {
373             *size = cborLen;
374         }
375     }
376
377     if ((CborNoError != cborEncoderResult) || (OC_STACK_OK != ret))
378     {
379         OICFree(outPayload);
380         outPayload = NULL;
381         *payload = NULL;
382         *size = 0;
383         ret = OC_STACK_ERROR;
384     }
385
386     return ret;
387 }
388
389 OCStackResult PstatToCBORPayload(const OicSecPstat_t *pstat,
390                                  uint8_t **payload, size_t *size)
391 {
392     bool allProps[PSTAT_PROPERTY_COUNT];
393
394     for (int i = 0; i < PSTAT_PROPERTY_COUNT; i++)
395     {
396         allProps[i] = true;
397     }
398
399     return PstatToCBORPayloadPartial(pstat, payload, size, allProps);
400 }
401
402 OCStackResult CBORPayloadToPstat(const uint8_t *cborPayload, const size_t size,
403                                  OicSecPstat_t **secPstat)
404 {
405     return CBORPayloadToPstatBin(cborPayload, size, secPstat, NULL, DOS_RESET);
406 }
407
408 static OCStackResult CBORPayloadToPstatBin(const uint8_t *cborPayload,
409                                            const size_t size,
410                                            OicSecPstat_t **secPstat,
411                                            bool *roParsed,
412                                            OicSecDeviceOnboardingState_t stateForReadOnlyCheck)
413 {
414     if (NULL == cborPayload || NULL == secPstat || NULL != *secPstat || 0 == size)
415     {
416         return OC_STACK_INVALID_PARAM;
417     }
418
419     OCStackResult ret = OC_STACK_ERROR;
420     CborValue pstatCbor = { .parser = NULL };
421     CborValue pstatMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
422     CborValue dosMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
423     CborParser parser = { .end = NULL };
424     CborError cborFindResult = CborNoError;
425     char *strUuid = NULL;
426     char *dosTagName = NULL;
427     size_t len = 0;
428     size_t dosLen = 0;
429     OicSecPstat_t *pstat = NULL;
430
431     *secPstat = NULL;
432
433     // init cbor parser
434     cbor_parser_init(cborPayload, size, 0, &parser, &pstatCbor);
435
436     // allocate pstat struct
437     pstat = (OicSecPstat_t *)OICCalloc(1, sizeof(OicSecPstat_t));
438     VERIFY_NOT_NULL(TAG, pstat, ERROR);
439
440     // Individual Properties missing from cbor representation may result in
441     // pstat Property assignment to existing gPstat values.  Therefore,
442     // we must ensure that gPstat to a valid value, to avoid null deref.
443     if (!gPstat)
444     {
445         gPstat = GetPstatDefault();
446     }
447     VERIFY_NOT_NULL(TAG, gPstat, FATAL);
448
449     // Enter pstat Map
450     cborFindResult = cbor_value_enter_container(&pstatCbor, &pstatMap);
451     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering pstat Map.");
452
453     // Find pstat.dos tag
454     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_DOS_NAME, &pstatMap);
455     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding dos tag.");
456
457     if (CborInvalidType != pstatMap.type)
458     {
459         // found pstat.dos tag "dos" in pstatMap
460         OIC_LOG(DEBUG, TAG, "Found pstat.dos tag in pstatMap.");
461         if (CborNoError == cborFindResult && cbor_value_is_container(&pstatMap))
462         {
463             OIC_LOG(DEBUG, TAG, "Found pstat.dos cbor container; entering.");
464             cborFindResult = cbor_value_enter_container(&pstatMap, &dosMap);
465             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering dos map.");
466             if (roParsed)
467             {
468                 if (IsPropertyReadOnly(PSTAT_DOS, stateForReadOnlyCheck))
469                 {
470                     *roParsed = true;
471                 }
472             }
473         }
474         while (cbor_value_is_valid(&dosMap) && cbor_value_is_text_string(&dosMap))
475         {
476             cborFindResult = cbor_value_dup_text_string(&dosMap, &dosTagName, &dosLen, NULL);
477             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting dos map next tag.");
478             cborFindResult = cbor_value_advance(&dosMap);
479             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing dos map.");
480
481             if (NULL != dosTagName)
482             {
483                 if (strcmp(dosTagName, OIC_JSON_S_NAME) == 0)
484                 {
485                     OIC_LOG(DEBUG, TAG, "Found pstat.dos.s tag; getting int value.");
486                     int s = -1;
487                     cborFindResult = cbor_value_get_int(&dosMap, &s);
488                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting pstat.dos.s value.");
489                     OIC_LOG_V(DEBUG, TAG, "Read pstat.dos.s value = %d.", s);
490                     pstat->dos.state = (OicSecDeviceOnboardingState_t)s;
491                 }
492                 else if (strcmp(dosTagName, OIC_JSON_P_NAME) == 0)
493                 {
494                     OIC_LOG(DEBUG, TAG, "Found pstat.dos.p tag; getting boolean value.");
495                     bool p = false;
496                     cborFindResult = cbor_value_get_boolean(&dosMap, &p);
497                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed getting pstat.dos.p value.");
498                     OIC_LOG_V(DEBUG, TAG, "Read pstat.dos.p value = %s.", p?"true":"false");
499                     pstat->dos.pending = p;
500                 }
501                 else
502                 {
503                     OIC_LOG_V(WARNING, TAG, "Unknown tag name in dos map: %s", dosTagName);
504                 }
505                 free(dosTagName);
506                 dosTagName = NULL;
507             }
508
509             if (cbor_value_is_valid(&dosMap))
510             {
511                 cborFindResult = cbor_value_advance(&dosMap);
512                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing dos map.");
513             }
514         }
515     }
516     else
517     {
518         // didn't find pstat.dos tag "dos" in pstatMap
519         OIC_LOG(WARNING, TAG, "Did not find mandatory pstat.dos tag in pstatMap.");
520         OIC_LOG(WARNING, TAG, "If this is not an intentionally-partial pstat representation,");
521         OIC_LOG(WARNING, TAG, "it may be an outdated .dat file that is missing the \"dos\" Property.");
522         OIC_LOG(WARNING, TAG, "Using existing pstat.dos value from gPstat.");
523         pstat->dos.state = gPstat->dos.state;
524         pstat->dos.pending = gPstat->dos.pending;
525         cborFindResult = CborNoError;
526     }
527
528     // pstat.isop Property
529     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ISOP_NAME, &pstatMap);
530     if (CborNoError == cborFindResult && cbor_value_is_boolean(&pstatMap))
531     {
532         cborFindResult = cbor_value_get_boolean(&pstatMap, &pstat->isOp);
533         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding isOp Value.");
534
535         if (roParsed)
536         {
537             if (IsPropertyReadOnly(PSTAT_ISOP, stateForReadOnlyCheck))
538             {
539                 *roParsed = true;
540             }
541         }
542     }
543     else
544     {
545         pstat->isOp = gPstat->isOp;
546         cborFindResult = CborNoError;
547     }
548
549     // pstat.cm Property
550     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_CM_NAME, &pstatMap);
551     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
552     {
553         int cm;
554
555         cborFindResult = cbor_value_get_int(&pstatMap, &cm);
556         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CM.");
557         pstat->cm = (OicSecDpm_t)cm;
558
559         if (roParsed)
560         {
561             if (IsPropertyReadOnly(PSTAT_CM, stateForReadOnlyCheck))
562             {
563                 *roParsed = true;
564             }
565         }
566     }
567     else
568     {
569         pstat->cm = gPstat->cm;
570         cborFindResult = CborNoError;
571     }
572
573     // pstat.tm Property
574     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_TM_NAME, &pstatMap);
575     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
576     {
577         int tm;
578
579         cborFindResult = cbor_value_get_int(&pstatMap, &tm);
580         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding TM.");
581         pstat->tm = (OicSecDpm_t)tm;
582
583         if (roParsed)
584         {
585             if (IsPropertyReadOnly(PSTAT_TM, stateForReadOnlyCheck))
586             {
587                 *roParsed = true;
588             }
589         }
590
591     }
592     else
593     {
594         pstat->tm = gPstat->tm;
595         cborFindResult = CborNoError;
596     }
597
598     // pstat.om Property
599     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_OM_NAME, &pstatMap);
600     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
601     {
602         int om;
603
604         cborFindResult = cbor_value_get_int(&pstatMap, &om);
605         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OM.");
606         pstat->om = (OicSecDpom_t)om;
607
608         if (roParsed)
609         {
610             if (IsPropertyReadOnly(PSTAT_OM, stateForReadOnlyCheck))
611             {
612                 *roParsed = true;
613             }
614         }
615     }
616     else
617     {
618         pstat->om = gPstat->om;
619         cborFindResult = CborNoError;
620     }
621
622     // pstat.sm Property
623     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_SM_NAME, &pstatMap);
624     if (CborNoError == cborFindResult && cbor_value_is_integer(&pstatMap))
625     {
626         int sm;
627
628         pstat->smLen = 1;
629         pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
630         VERIFY_NOT_NULL(TAG, pstat->sm, ERROR);
631         cborFindResult = cbor_value_get_int(&pstatMap, &sm);
632         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SM.");
633         pstat->sm[0] = (OicSecDpom_t)sm;
634
635         if (roParsed)
636         {
637             if (IsPropertyReadOnly(PSTAT_SM, stateForReadOnlyCheck))
638             {
639                 *roParsed = true;
640             }
641         }
642     }
643     else
644     {
645         VERIFY_NOT_NULL(TAG, gPstat, ERROR);
646         pstat->smLen = gPstat->smLen;
647         pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
648         VERIFY_NOT_NULL(TAG, pstat->sm, ERROR);
649         *pstat->sm = *gPstat->sm;
650         cborFindResult = CborNoError;
651     }
652
653     // pstat.rowneruuid Property
654     cborFindResult = cbor_value_map_find_value(&pstatCbor, OIC_JSON_ROWNERID_NAME, &pstatMap);
655     if (CborNoError == cborFindResult && cbor_value_is_text_string(&pstatMap))
656     {
657         cborFindResult = cbor_value_dup_text_string(&pstatMap, &strUuid , &len, NULL);
658         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ROwner Id Value.");
659         ret = ConvertStrToUuid(strUuid , &pstat->rownerID);
660         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
661         OICFree(strUuid );
662         strUuid  = NULL;
663         if (roParsed)
664         {
665             if (IsPropertyReadOnly(PSTAT_ROWNERUUID, stateForReadOnlyCheck))
666             {
667                 *roParsed = true;
668             }
669         }
670     }
671     else
672     {
673         VERIFY_NOT_NULL(TAG, gPstat, ERROR);
674         memcpy(pstat->rownerID.id, gPstat->rownerID.id, sizeof(gPstat->rownerID.id));
675         cborFindResult = CborNoError;
676     }
677
678     *secPstat = pstat;
679
680     ret = OC_STACK_OK;
681
682 exit:
683     if (CborNoError != cborFindResult)
684     {
685         OIC_LOG(ERROR, TAG, "CBORPayloadToPstat failed");
686         DeletePstatBinData(pstat);
687         pstat = NULL;
688         *secPstat = NULL;
689         ret = OC_STACK_ERROR;
690     }
691
692     return ret;
693 }
694
695 static bool ValidateQuery(const char * query)
696 {
697     OIC_LOG (DEBUG, TAG, "In ValidateQuery");
698     if(NULL == gPstat)
699     {
700         return false;
701     }
702
703     bool bInterfaceQry = false;      // does querystring contains 'if' query ?
704     bool bInterfaceMatch = false;    // does 'if' query matches with oic.if.baseline ?
705
706     OicParseQueryIter_t parseIter = {.attrPos = NULL};
707
708     ParseQueryIterInit((unsigned char*)query, &parseIter);
709
710     while (GetNextQuery(&parseIter))
711     {
712         if (strncasecmp((char *)parseIter.attrPos, OC_RSRVD_INTERFACE, parseIter.attrLen) == 0)
713         {
714             bInterfaceQry = true;
715             if ((strncasecmp((char *)parseIter.valPos, OC_RSRVD_INTERFACE_DEFAULT, parseIter.valLen) == 0))
716             {
717                 bInterfaceMatch = true;
718             }
719         }
720     }
721     return (bInterfaceQry ? bInterfaceMatch: true);
722 }
723
724 /**
725  * The entity handler determines how to process a GET request.
726  */
727 static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
728 {
729     OCEntityHandlerResult ehRet = OC_EH_OK;
730
731     OIC_LOG(INFO, TAG, "HandlePstatGetRequest  processing GET request");
732
733     //Checking if Get request is a query.
734     if (ehRequest->query)
735     {
736         OIC_LOG_V(DEBUG,TAG,"query:%s",ehRequest->query);
737         OIC_LOG(DEBUG, TAG, "HandlePstatGetRequest processing query");
738         if (!ValidateQuery(ehRequest->query))
739         {
740             ehRet = OC_EH_ERROR;
741         }
742     }
743
744     /*
745      * For GET or Valid Query request return pstat resource CBOR payload.
746      * For non-valid query return NULL payload.
747      * A device will 'always' have a default Pstat, so PstatToCBORPayload will
748      * return valid pstat resource json.
749      */
750     size_t size = 0;
751     uint8_t *payload = NULL;
752     if (ehRet == OC_EH_OK)
753     {
754         if(OC_STACK_OK != PstatToCBORPayload(gPstat, &payload, &size))
755         {
756             OIC_LOG_V(WARNING, TAG, "%s PstatToCBORPayload failed.", __func__);
757         }
758     }
759
760     // Send response payload to request originator
761     ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
762                    OC_EH_OK : OC_EH_ERROR;
763     OICFree(payload);
764     return ehRet;
765 }
766
767 /**
768  * The entity handler determines how to process a POST request.
769  * Per the REST paradigm, POST can also be used to update representation of existing
770  * resource or create a new resource.
771  * For pstat, it updates only dos, tm, om, and rowneruuid.
772  */
773 static OCEntityHandlerResult HandlePstatPostRequest(OCEntityHandlerRequest *ehRequest)
774 {
775     OCEntityHandlerResult ehRet = OC_EH_ERROR;
776     OIC_LOG(INFO, TAG, "HandlePstatPostRequest  processing POST request");
777     OicSecPstat_t *pstat = NULL;
778     static uint16_t previousMsgId = 0;
779     bool isDuplicatedMsg = false;
780
781     if (ehRequest->payload && NULL != gPstat)
782     {
783         uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
784         size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
785         VERIFY_NOT_NULL(TAG, payload, ERROR);
786
787         bool roParsed = false;
788         OCStackResult ret = CBORPayloadToPstatBin(payload, size, &pstat,
789                                                   &roParsed, gPstat->dos.state);
790         VERIFY_NOT_NULL(TAG, pstat, ERROR);
791
792         // if CBOR parsing OK
793         if (OC_STACK_OK == ret)
794         {
795             /*
796              * message ID is supported for CoAP over UDP only according to RFC 7252
797              * So we should check message ID to prevent duplicate request handling in case of OC_ADAPTER_IP.
798              * In case of other transport adapter, duplicate message check is not required.
799              */
800             if (OC_ADAPTER_IP == ehRequest->devAddr.adapter &&
801                  previousMsgId == ehRequest->messageID)
802             {
803                 isDuplicatedMsg = true;
804             }
805
806             if (true == roParsed)
807             {
808                     OIC_LOG(ERROR, TAG, "Not acceptable request because of read-only properties");
809                     ehRet = OC_EH_NOT_ACCEPTABLE;
810                     goto exit;
811             }
812
813             // operation mode (om) should be one of supported modes (sm)
814             bool supportedOm = false;
815             for(size_t i = 0; i < gPstat->smLen; i++)
816             {
817                 if(gPstat->sm[i] == pstat->om)
818                 {
819                     OIC_LOG_V(ERROR, TAG, "%s: %d is a supported Operation Mode",
820                         __func__, (int) pstat->om);
821                     supportedOm = true;
822                 }
823             }
824             if (!supportedOm)
825             {
826                 OIC_LOG_V(ERROR, TAG, "%s: %d is NOT a supported Operation Mode",
827                     __func__, (int) pstat->om);
828                 ehRet = OC_EH_BAD_REQ;
829                 goto exit;
830             }
831
832             if (!(gPstat->tm & VERIFY_SOFTWARE_VERSION)
833                 && (pstat->tm & VERIFY_SOFTWARE_VERSION)) { // ISVV bit goes from 0 to 1
834                 OIC_LOG (INFO, TAG, "Software Version Validation process initiated");
835                 pstat->cm &= ~VERIFY_SOFTWARE_VERSION; // Unset the cm bit, per spec
836             }
837
838             if (!(gPstat->tm & UPDATE_SOFTWARE)
839                 && (pstat->tm & UPDATE_SOFTWARE)) { // ISSU bit goes from 0 to 1
840                 OIC_LOG (INFO, TAG, "Software Update process initiated");
841                 pstat->cm &= ~UPDATE_SOFTWARE; // Unset the cm bit, per spec
842             }
843
844             if (pstat->dos.state != gPstat->dos.state)
845             {
846                 OCStackResult stateChangeResult = OC_STACK_ERROR;
847                 stateChangeResult = SetDosState(pstat->dos.state);
848                 switch (stateChangeResult)
849                 {
850                     case OC_STACK_OK:
851                     OIC_LOG_V(INFO, TAG, "%s: DOS state changed SUCCESSFULLY to %d.", \
852                         __func__, pstat->dos.state);
853                     ehRet = OC_EH_OK;
854                     break;
855
856                     case OC_STACK_FORBIDDEN_REQ:
857                     OIC_LOG_V(WARNING, TAG, "%s: DOS state change change to %d NOT ALLOWED.", \
858                         __func__, pstat->dos.state);
859                     ehRet = OC_EH_NOT_ACCEPTABLE;
860                     goto exit;
861                     break;
862
863                     case OC_STACK_INTERNAL_SERVER_ERROR:
864                     default:
865                     OIC_LOG_V(ERROR, TAG, "%s: DOS state change change to %d FAILED. \
866                         Internal error - SVRs may be in bad state.", \
867                         __func__, pstat->dos.state);
868                     ehRet = OC_EH_INTERNAL_SERVER_ERROR;
869                     goto exit;
870                     break;
871                 }
872             }
873
874             // update om
875             gPstat->om = pstat->om;
876
877             // update rownerID
878             gPstat->rownerID = pstat->rownerID;
879
880             // Convert pstat data into CBOR for update to persistent storage
881             if (UpdatePersistentStorage(gPstat))
882             {
883                 ehRet = OC_EH_OK;
884             }
885             if (true == (pstat->cm & RESET))
886             {
887                 if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
888                 {
889                     ehRet = OC_EH_ERROR;
890                     OIC_LOG_V(ERROR, TAG, "%s: SendSRMResponse failed.", __func__);
891                     DeletePstatBinData(pstat);
892                     return ehRet;
893                 }
894                 ret = ResetSecureResourceInPS();
895                 if (OC_STACK_OK == ret)
896                 {
897                     ehRet = OC_EH_OK;
898                 }
899                 DeletePstatBinData(pstat);
900                 return ehRet;
901             }
902         }
903     }
904
905     exit:
906
907     // TODO [IOT-1796] This is another place error code returns need to be
908     // cleaned up.
909     if (OC_EH_OK != ehRet)
910     {
911         /*
912          * If some error is occured while ownership transfer,
913          * ownership transfer related resource should be revert back to initial status.
914          */
915         OIC_LOG(WARNING, TAG, "The operation failed during handle pstat POST request");
916         const OicSecDoxm_t* doxm = GetDoxmResourceData();
917         if (doxm)
918         {
919             if (!doxm->owned)
920             {
921                 if (!isDuplicatedMsg)
922                 {
923                     OIC_LOG(WARNING, TAG, "DOXM and PSTAT will be reverted.");
924                     RestoreDoxmToInitState();
925                     RestorePstatToInitState();
926                 }
927             }
928         }
929         else
930         {
931            OIC_LOG(ERROR, TAG, "Invalid DOXM resource.");
932         }
933     }
934     else
935     {
936         if (ehRequest->devAddr.adapter == OC_ADAPTER_IP)
937         {
938             previousMsgId = ehRequest->messageID;
939         }
940     }
941
942     // Send response payload to request originator
943     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
944         OC_EH_OK : OC_EH_ERROR;
945
946     DeletePstatBinData(pstat);
947
948     return ehRet;
949 }
950
951 /**
952  * This internal method is the entity handler for pstat resources.
953  */
954  OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
955                                           OCEntityHandlerRequest * ehRequest,
956                                           void *callbackParam)
957 {
958     (void)callbackParam;
959     OCEntityHandlerResult ehRet = OC_EH_ERROR;
960     // This method will handle REST request (GET/POST) for /oic/sec/pstat
961     if (flag & OC_REQUEST_FLAG)
962     {
963         OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
964         switch (ehRequest->method)
965         {
966             case OC_REST_GET:
967                 ehRet = HandlePstatGetRequest(ehRequest);
968                 break;
969             case OC_REST_POST:
970                 ehRet = HandlePstatPostRequest(ehRequest);
971                 break;
972             default:
973                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
974                     OC_EH_OK : OC_EH_ERROR;
975                 break;
976         }
977     }
978     return ehRet;
979 }
980
981 /**
982  * This internal method is used to create '/oic/sec/pstat' resource.
983  */
984  OCStackResult CreatePstatResource()
985 {
986     OCStackResult ret = OCCreateResource(&gPstatHandle,
987                                          OIC_RSRC_TYPE_SEC_PSTAT,
988                                          OC_RSRVD_INTERFACE_DEFAULT,
989                                          OIC_RSRC_PSTAT_URI,
990                                          PstatEntityHandler,
991                                          NULL,
992                                          OC_SECURE |
993                                          OC_DISCOVERABLE);
994
995     if (OC_STACK_OK != ret)
996     {
997         OIC_LOG(FATAL, TAG, "Unable to instantiate pstat resource");
998         DeInitPstatResource();
999     }
1000     return ret;
1001 }
1002
1003 OCStackResult InitPstatResource()
1004 {
1005     OCStackResult ret = OC_STACK_ERROR;
1006
1007     // Read Pstat resource from PS
1008     uint8_t *data = NULL;
1009     size_t size = 0;
1010     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_PSTAT_NAME, &data, &size);
1011     // If database read failed
1012     if (OC_STACK_OK != ret)
1013     {
1014         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1015     }
1016     if (data)
1017     {
1018         // Read ACL resource from PS
1019         ret = CBORPayloadToPstat(data, size, &gPstat);
1020         OICFree(data);
1021     }
1022     /*
1023      * If SVR database in persistent storage got corrupted or
1024      * is not available for some reason, a default pstat is created
1025      * which allows user to initiate pstat provisioning again.
1026      */
1027     if ((OC_STACK_OK != ret) || !gPstat)
1028     {
1029         gPstat = GetPstatDefault();
1030     }
1031     VERIFY_NOT_NULL(TAG, gPstat, FATAL);
1032
1033     // TODO [IOT-2023]: after all SVRs are initialized, need to call SetDosState()
1034     // using the just-loaded pstat.dos.s
1035
1036     // Instantiate 'oic.sec.pstat'
1037     ret = CreatePstatResource();
1038
1039 exit:
1040     if (OC_STACK_OK != ret)
1041     {
1042         DeInitPstatResource();
1043     }
1044     return ret;
1045 }
1046
1047 OCStackResult InitPstatResourceToDefault()
1048 {
1049     gPstat = GetPstatDefault();
1050     VERIFY_NOT_NULL(TAG, gPstat, FATAL);
1051
1052     return OC_STACK_OK;
1053 exit:
1054     return OC_STACK_ERROR;
1055 }
1056
1057 OCStackResult DeInitPstatResource()
1058 {
1059     if (gPstat != &gDefaultPstat)
1060     {
1061         DeletePstatBinData(gPstat);
1062         gPstat = NULL;
1063     }
1064     return OCDeleteResource(gPstatHandle);
1065 }
1066
1067 /**
1068  * Function to restore pstat resurce to initial status.
1069  * This function will use in case of error while ownership transfer
1070  */
1071 void RestorePstatToInitState()
1072 {
1073     if(gPstat)
1074     {
1075         OIC_LOG(INFO, TAG, "PSTAT resource will revert back to initial status.");
1076         gPstat->dos.state = DOS_RFOTM;
1077         gPstat->dos.pending = false;
1078         gPstat->cm = (OicSecDpm_t)(gPstat->cm | TAKE_OWNER);
1079         gPstat->tm = (OicSecDpm_t)(gPstat->tm & (~TAKE_OWNER));
1080         gPstat->om = SINGLE_SERVICE_CLIENT_DRIVEN;
1081         if(gPstat->sm && 0 < gPstat->smLen)
1082         {
1083             gPstat->sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
1084         }
1085
1086         if (!UpdatePersistentStorage(gPstat))
1087         {
1088             OIC_LOG(ERROR, TAG, "Failed to revert PSTAT in persistent storage");
1089         }
1090     }
1091 }
1092
1093 OCStackResult GetPstatRownerId(OicUuid_t *rowneruuid)
1094 {
1095     if (gPstat && rowneruuid)
1096     {
1097         memcpy(&(rowneruuid->id), &(gPstat->rownerID.id), sizeof(rowneruuid->id));
1098         return OC_STACK_OK;
1099     }
1100     return OC_STACK_ERROR;
1101 }
1102
1103 OCStackResult SetPstatRownerId(const OicUuid_t *rowneruuid)
1104 {
1105     OCStackResult ret = OC_STACK_ERROR;
1106     uint8_t *cborPayload = NULL;
1107     size_t size = 0;
1108     OicUuid_t prevId = {.id={0}};
1109
1110     if(NULL == rowneruuid)
1111     {
1112         ret = OC_STACK_INVALID_PARAM;
1113     }
1114     if(NULL == gPstat)
1115     {
1116         ret = OC_STACK_NO_RESOURCE;
1117     }
1118
1119     if(rowneruuid && gPstat)
1120     {
1121         memcpy(prevId.id, gPstat->rownerID.id, sizeof(prevId.id));
1122         memcpy(gPstat->rownerID.id, rowneruuid->id, sizeof(gPstat->rownerID.id));
1123
1124         ret = PstatToCBORPayload(gPstat, &cborPayload, &size);
1125         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1126
1127         ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size);
1128         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1129
1130         OICFree(cborPayload);
1131     }
1132
1133     return ret;
1134
1135 exit:
1136     OICFree(cborPayload);
1137     memcpy(gPstat->rownerID.id, prevId.id, sizeof(gPstat->rownerID.id));
1138     return ret;
1139 }
1140
1141 OCStackResult GetPstatDosS(OicSecDeviceOnboardingState_t *s)
1142 {
1143     if (gPstat && s)
1144     {
1145         *s = gPstat->dos.state;
1146         return OC_STACK_OK;
1147     }
1148     return OC_STACK_ERROR;
1149 }
1150
1151 OCStackResult SetPstatDosS(const OicSecDeviceOnboardingState_t s)
1152 {
1153     if (gPstat)
1154     {
1155         gPstat->dos.state = s;
1156         return OC_STACK_OK;
1157     }
1158     return OC_STACK_ERROR;
1159 }
1160
1161 OCStackResult GetPstatDosP(bool *p)
1162 {
1163     if (gPstat && p)
1164     {
1165         *p = gPstat->dos.pending;
1166         return OC_STACK_OK;
1167     }
1168     return OC_STACK_ERROR;
1169 }
1170
1171 OCStackResult SetPstatDosP(const bool p)
1172 {
1173     if (gPstat)
1174     {
1175         gPstat->dos.pending = p;
1176         return OC_STACK_OK;
1177     }
1178     return OC_STACK_ERROR;
1179 }
1180
1181 OCStackResult GetPstatIsop(bool *isop)
1182 {
1183     if (gPstat && isop)
1184     {
1185         *isop = gPstat->isOp;
1186         return OC_STACK_OK;
1187     }
1188     return OC_STACK_ERROR;
1189 }
1190
1191 OCStackResult SetPstatIsop(const bool isop)
1192 {
1193     if (gPstat)
1194     {
1195         gPstat->isOp = isop;
1196         return OC_STACK_OK;
1197     }
1198     return OC_STACK_ERROR;
1199 }
1200
1201 OCStackResult GetPstatCm(OicSecDpm_t *cm)
1202 {
1203     if (gPstat && cm)
1204     {
1205         *cm = gPstat->cm;
1206         return OC_STACK_OK;
1207     }
1208     return OC_STACK_ERROR;
1209 }
1210
1211 OCStackResult SetPstatCm(const OicSecDpm_t cm)
1212 {
1213     if (gPstat)
1214     {
1215         gPstat->cm = cm;
1216         return OC_STACK_OK;
1217     }
1218     return OC_STACK_ERROR;
1219 }
1220
1221 OCStackResult GetPstatTm(OicSecDpm_t *tm)
1222 {
1223     if (gPstat && tm)
1224     {
1225         *tm = gPstat->tm;
1226         return OC_STACK_OK;
1227     }
1228     return OC_STACK_ERROR;
1229 }
1230
1231 OCStackResult SetPstatTm(const OicSecDpm_t tm)
1232 {
1233     if (gPstat)
1234     {
1235         gPstat->tm = tm;
1236         return OC_STACK_OK;
1237     }
1238     return OC_STACK_ERROR;
1239 }
1240
1241 OCStackResult SetPstatSelfOwnership(const OicUuid_t* newROwner)
1242 {
1243     OCStackResult ret = OC_STACK_ERROR;
1244     uint8_t *cborPayload = NULL;
1245     size_t size = 0;
1246
1247     if(NULL == gPstat)
1248     {
1249         ret = OC_STACK_NO_RESOURCE;
1250         return ret;
1251     }
1252
1253     if( newROwner && (false == gPstat->isOp) && (TAKE_OWNER & gPstat->cm) )
1254     {
1255         gPstat->cm = (OicSecDpm_t)(gPstat->cm & (~TAKE_OWNER));
1256         gPstat->isOp = true;
1257
1258         memcpy(gPstat->rownerID.id, newROwner->id, sizeof(newROwner->id));
1259
1260         ret = PstatToCBORPayload(gPstat, &cborPayload, &size);
1261         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1262
1263         ret = UpdateSecureResourceInPS(OIC_JSON_PSTAT_NAME, cborPayload, size);
1264         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1265
1266         OICFree(cborPayload);
1267     }
1268     else
1269     {
1270         OIC_LOG(ERROR, TAG, "The state of PSTAT is not Ready For OTM");
1271     }
1272
1273     return ret;
1274
1275 exit:
1276     OICFree(cborPayload);
1277     return ret;
1278 }
1279