[IOT-1884] Allow IoTivity to generate and persist PIID
[platform/upstream/iotivity.git] / resource / csdk / security / src / psinterface.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 #ifdef WITH_ARDUINO
22 #define __STDC_LIMIT_MACROS
23 #endif
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
28
29 #include "cainterface.h"
30 #include "logger.h"
31 #include "ocpayload.h"
32 #include "ocpayloadcbor.h"
33 #include "ocstack.h"
34 #include "oic_malloc.h"
35 #include "payload_logging.h"
36 #include "resourcemanager.h"
37 #include "secureresourcemanager.h"
38 #include "srmresourcestrings.h"
39 #include "srmutility.h"
40 #include "pstatresource.h"
41 #include "doxmresource.h"
42 #include "ocresourcehandler.h"
43
44 #define TAG  "OIC_SRM_PSI"
45
46 /**
47  * Helps cover adding the name of the resource, map addition, and ending while
48  * performing CBOR encoding.
49  */
50 #define CBOR_ENCODING_SIZE_ADDITION 255
51
52 /**
53  * Virtual database buffer block size
54  */
55 #ifdef _WIN32
56 #define DB_FILE_SIZE_BLOCK 1023
57 #else
58 const size_t DB_FILE_SIZE_BLOCK = 1023;
59 #endif
60
61 typedef enum _PSDatabase
62 {
63     PS_DATABASE_SECURITY = 0,
64     PS_DATABASE_DEVICEPROPERTIES
65 } PSDatabase;
66
67 /**
68  * Writes CBOR payload to the specified database in persistent storage.
69  *
70  * @param databaseName is the name of the database to access through persistent storage.
71  * @param payload      is the CBOR payload to write to the database in persistent storage.
72  * @param size         is the size of payload.
73  *
74  * @return ::OC_STACK_OK for Success, otherwise some error value
75  */
76 static OCStackResult WritePayloadToPS(const char *databaseName, uint8_t *payload, size_t size)
77 {
78     if (!databaseName || !payload || (size <= 0))
79     {
80         OC_STACK_INVALID_PARAM;
81     }
82
83     OCStackResult result = OC_STACK_ERROR;
84
85     OIC_LOG_V(DEBUG, TAG, "Writing in the file: %" PRIuPTR, size);
86
87     OCPersistentStorage* ps = OCGetPersistentStorageHandler();
88     if (ps)
89     {
90         FILE *fp = ps->open(databaseName, "wb");
91         if (fp)
92         {
93             size_t numberItems = ps->write(payload, 1, size, fp);
94             if (size == numberItems)
95             {
96                 OIC_LOG_V(DEBUG, TAG, "Written %" PRIuPTR " bytes into %s", size, databaseName);
97                 result = OC_STACK_OK;
98             }
99             else
100             {
101                 OIC_LOG_V(ERROR, TAG, "Failed writing %" PRIuPTR " in %s", numberItems, databaseName);
102             }
103             ps->close(fp);
104         }
105         else
106         {
107             OIC_LOG(ERROR, TAG, "File open failed.");
108         }
109     }
110
111     return result;
112 }
113
114 /**
115  * Gets the database size
116  *
117  * @param ps            is a pointer to OCPersistentStorage for the Virtual Resource(s).
118  * @param databaseName  is the name of the database to access through persistent storage.
119  *
120  * @return size_t - total size of the database
121  */
122 static size_t GetDatabaseSize(const OCPersistentStorage *ps, const char *databaseName)
123 {
124     if (!ps)
125     {
126         return 0;
127     }
128     size_t size = 0;
129     char buffer[DB_FILE_SIZE_BLOCK];  // can not initialize with declaration
130                                       // but maybe not needed to initialize
131     FILE *fp = ps->open(databaseName, "rb");
132     if (fp)
133     {
134         size_t bytesRead = 0;
135         do
136         {
137             bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
138             size += bytesRead;
139         } while (bytesRead);
140         ps->close(fp);
141     }
142     return size;
143 }
144
145 /**
146  * Reads the database from PS
147  * 
148  * @note Caller of this method MUST use OICFree() method to release memory
149  *       referenced by the data argument.
150  *
151  * @param databaseName is the name of the database to access through persistent storage.
152  * @param resourceName is the name of the field for which file content are read.
153  *                     if the value is NULL it will send the content of the whole file.
154  * @param data         is the pointer to the file contents read from the database.
155  * @param size         is the size of the file contents read.
156  *
157  * @return ::OC_STACK_OK for Success, otherwise some error value
158  */
159 OCStackResult ReadDatabaseFromPS(const char *databaseName, const char *resourceName, uint8_t **data, size_t *size)
160 {
161     OIC_LOG(DEBUG, TAG, "ReadDatabaseFromPS IN");
162
163     if (!databaseName || !data || *data || !size)
164     {
165         return OC_STACK_INVALID_PARAM;
166     }
167
168     FILE *fp = NULL;
169     uint8_t *fsData = NULL;
170     size_t fileSize = 0;
171     OCStackResult ret = OC_STACK_ERROR;
172
173     OCPersistentStorage *ps = OCGetPersistentStorageHandler();
174     VERIFY_NOT_NULL(TAG, ps, ERROR);
175
176     fileSize = GetDatabaseSize(ps, databaseName);
177     OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
178     if (fileSize)
179     {
180         fsData = (uint8_t *) OICCalloc(1, fileSize);
181         VERIFY_NOT_NULL(TAG, fsData, ERROR);
182
183         fp = ps->open(databaseName, "rb");
184         VERIFY_NOT_NULL(TAG, fp, ERROR);
185         if (ps->read(fsData, 1, fileSize, fp) == fileSize)
186         {
187             if (resourceName)
188             {
189                 CborParser parser;  // will be initialized in |cbor_parser_init|
190                 CborValue cbor;     // will be initialized in |cbor_parser_init|
191                 cbor_parser_init(fsData, fileSize, 0, &parser, &cbor);
192                 CborValue cborValue = {0};
193                 CborError cborFindResult = cbor_value_map_find_value(&cbor, resourceName, &cborValue);
194                 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&cborValue))
195                 {
196                     cborFindResult = cbor_value_dup_byte_string(&cborValue, data, size, NULL);
197                     VERIFY_SUCCESS(TAG, CborNoError == cborFindResult, ERROR);
198                     ret = OC_STACK_OK;
199                 }
200                 // in case of |else (...)|, svr_data not found
201             }
202             // return everything in case resourceName is NULL
203             else
204             {
205                 *size = fileSize;
206                 *data = (uint8_t *) OICCalloc(1, fileSize);
207                 VERIFY_NOT_NULL(TAG, *data, ERROR);
208                 memcpy(*data, fsData, fileSize);
209                 ret = OC_STACK_OK;
210             }
211         }
212     }
213     OIC_LOG(DEBUG, TAG, "ReadDatabaseFromPS OUT");
214
215 exit:
216     if (fp)
217     {
218         ps->close(fp);
219     }
220     OICFree(fsData);
221     return ret;
222 }
223
224 /**
225  * This method updates the database in PS
226  *
227  * @param databaseName  is the name of the database to access through persistent storage.
228  * @param resourceName  is the name of the resource that will be updated.
229  * @param payload       is the pointer to memory where the CBOR payload is located.
230  * @param size          is the size of the CBOR payload.
231  *
232  * @return ::OC_STACK_OK for Success, otherwise some error value
233  */
234 OCStackResult UpdateResourceInPS(const char *databaseName, const char *resourceName, const uint8_t *payload, size_t size)
235 {
236     OIC_LOG(DEBUG, TAG, "UpdateResourceInPS IN");
237     if (!databaseName || !resourceName)
238     {
239         return OC_STACK_INVALID_PARAM;
240     }
241
242     size_t dbSize = 0;
243     size_t outSize = 0;
244     uint8_t *dbData = NULL;
245     uint8_t *outPayload = NULL;
246
247     uint8_t *aclCbor = NULL;
248     uint8_t *pstatCbor = NULL;
249     uint8_t *doxmCbor = NULL;
250     uint8_t *amaclCbor = NULL;
251     uint8_t *credCbor = NULL;
252     uint8_t *pconfCbor = NULL;
253     uint8_t *resetPfCbor = NULL;
254     uint8_t *crlCbor = NULL;
255     uint8_t *dpCbor = NULL;
256
257     int64_t cborEncoderResult = CborNoError;
258     OCStackResult ret = ReadDatabaseFromPS(databaseName, NULL, &dbData, &dbSize);
259     if (dbData && dbSize)
260     {
261         PSDatabase database = PS_DATABASE_SECURITY;
262         size_t allocSize = 0;
263         size_t aclCborLen = 0;
264         size_t pstatCborLen = 0;
265         size_t doxmCborLen = 0;
266         size_t amaclCborLen = 0;
267         size_t credCborLen = 0;
268         size_t pconfCborLen = 0;
269         size_t resetPfCborLen = 0;
270         size_t crlCborLen = 0;
271         size_t dpCborLen = 0;
272
273         // Determine which database we are working with so we can scope our operations
274         if (0 == strcmp(OC_DEVICE_PROPS_FILE_NAME, databaseName))
275         {
276             database = PS_DATABASE_DEVICEPROPERTIES;
277         }
278
279         // Gets each secure virtual resource from persistent storage
280         // this local scoping intended, for destroying large cbor instances after use
281         {
282             CborParser parser;  // will be initialized in |cbor_parser_init|
283             CborValue cbor;     // will be initialized in |cbor_parser_init|
284             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
285             CborValue curVal = {0};
286             CborError cborFindResult = CborNoError;
287
288             // Only search for and copy resources owned by the target database
289             if (PS_DATABASE_SECURITY == database)
290             {
291                 // Security database
292                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
293                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
294                 {
295                     cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
296                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
297                 }
298                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
299                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
300                 {
301                     cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
302                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
303                 }
304                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
305                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
306                 {
307                     cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
308                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
309                 }
310                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_AMACL_NAME, &curVal);
311                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
312                 {
313                     cborFindResult = cbor_value_dup_byte_string(&curVal, &amaclCbor, &amaclCborLen, NULL);
314                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMACL Name Value.");
315                 }
316                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
317                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
318                 {
319                     cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
320                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
321                 }
322                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PCONF_NAME, &curVal);
323                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
324                 {
325                     cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
326                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
327                 }
328                 cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
329                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
330                 {
331                     cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
332                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
333                 }
334                 int64_t cborFindCrlResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRL_NAME, &curVal);
335                 if ((CborNoError == cborFindCrlResult) && cbor_value_is_byte_string(&curVal))
336                 {
337                     cborFindCrlResult = cbor_value_dup_byte_string(&curVal, &crlCbor, &crlCborLen, NULL);
338                     if ((CborNoError != cborFindCrlResult) && (CborErrorOutOfMemory != cborFindCrlResult))
339                     {
340                         OIC_LOG(ERROR, TAG, "Failed Finding optional CRL Name Value.");
341                     }
342                     else
343                     {
344                         OIC_LOG(INFO, TAG, "Successfully Finding optional CRL Name Value.");
345                     }
346                 }
347             }
348             else
349             {
350                 // Device Properties database
351                 cborFindResult = cbor_value_map_find_value(&cbor, OC_JSON_DEVICE_PROPS_NAME, &curVal);
352                 if ((CborNoError == cborFindResult) && cbor_value_is_byte_string(&curVal))
353                 {
354                     cborFindResult = cbor_value_dup_byte_string(&curVal, &dpCbor, &dpCborLen, NULL);
355                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Device Properties Name Value.");
356                 }
357             }
358         }
359
360         // Updates the added |payload| with the existing secure virtual resource(s)
361         // this local scoping intended, for destroying large cbor instances after use
362         {
363             if (PS_DATABASE_SECURITY == database)
364             {
365                 allocSize = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
366                           + credCborLen + pconfCborLen + resetPfCborLen + crlCborLen
367                           + size + CBOR_ENCODING_SIZE_ADDITION;
368             }
369             else
370             {
371                 allocSize = dpCborLen + size + CBOR_ENCODING_SIZE_ADDITION;
372             }
373
374
375             outPayload = (uint8_t *)OICCalloc(1, allocSize);
376             VERIFY_NOT_NULL(TAG, outPayload, ERROR);
377             CborEncoder encoder;  // will be initialized in |cbor_parser_init|
378             cbor_encoder_init(&encoder, outPayload, allocSize, 0);
379             CborEncoder resource;  // will be initialized in |cbor_encoder_create_map|
380             cborEncoderResult |= cbor_encoder_create_map(&encoder, &resource, CborIndefiniteLength);
381             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
382
383             if (payload && size)
384             {
385                 cborEncoderResult |= cbor_encode_text_string(&resource, resourceName, strlen(resourceName));
386                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
387                 cborEncoderResult |= cbor_encode_byte_string(&resource, payload, size);
388                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
389             }
390
391             if (PS_DATABASE_SECURITY == database)
392             {
393                 // Security database
394                 if (strcmp(OIC_JSON_ACL_NAME, resourceName) && aclCborLen)
395                 {
396                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
397                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
398                     cborEncoderResult |= cbor_encode_byte_string(&resource, aclCbor, aclCborLen);
399                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
400                 }
401                 else if (strcmp(OIC_JSON_PSTAT_NAME, resourceName) && pstatCborLen)
402                 {
403                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
404                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
405                     cborEncoderResult |= cbor_encode_byte_string(&resource, pstatCbor, pstatCborLen);
406                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
407                 }
408                 else if (strcmp(OIC_JSON_DOXM_NAME, resourceName) && doxmCborLen)
409                 {
410                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
411                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
412                     cborEncoderResult |= cbor_encode_byte_string(&resource, doxmCbor, doxmCborLen);
413                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
414                 }
415                 else if (strcmp(OIC_JSON_AMACL_NAME, resourceName) && amaclCborLen)
416                 {
417                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME));
418                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Name.");
419                     cborEncoderResult |= cbor_encode_byte_string(&resource, amaclCbor, amaclCborLen);
420                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Value.");
421                 }
422                 else if (strcmp(OIC_JSON_CRED_NAME, resourceName) && credCborLen)
423                 {
424                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
425                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Name.");
426                     cborEncoderResult |= cbor_encode_byte_string(&resource, credCbor, credCborLen);
427                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Value.");
428                 }
429                 else if (strcmp(OIC_JSON_PCONF_NAME, resourceName) && pconfCborLen)
430                 {
431                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_PCONF_NAME, strlen(OIC_JSON_PCONF_NAME));
432                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Name.");
433                     cborEncoderResult |= cbor_encode_byte_string(&resource, pconfCbor, pconfCborLen);
434                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
435                 }
436                 else if (strcmp(OIC_JSON_RESET_PF_NAME, resourceName) && resetPfCborLen)
437                 {
438                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
439                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
440                     cborEncoderResult |= cbor_encode_byte_string(&resource, resetPfCbor, resetPfCborLen);
441                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
442                 }
443                 else if (strcmp(OIC_JSON_CRL_NAME, resourceName) && crlCborLen)
444                 {
445                     cborEncoderResult |= cbor_encode_text_string(&resource, OIC_JSON_CRL_NAME, strlen(OIC_JSON_CRL_NAME));
446                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Name.");
447                     cborEncoderResult |= cbor_encode_byte_string(&resource, crlCbor, crlCborLen);
448                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Value.");
449                 }
450             }
451             else
452             {
453                 // Device Properties database
454                 if (strcmp(OC_JSON_DEVICE_PROPS_NAME, resourceName) && dpCborLen)
455                 {
456                     cborEncoderResult |= cbor_encode_text_string(&resource, OC_JSON_DEVICE_PROPS_NAME, strlen(OC_JSON_DEVICE_PROPS_NAME));
457                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Properties Name.");
458                     cborEncoderResult |= cbor_encode_byte_string(&resource, dpCbor, dpCborLen);
459                     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Device Properties Value.");
460                 }
461             }
462
463             cborEncoderResult |= cbor_encoder_close_container(&encoder, &resource);
464             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
465             outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
466         }
467     }
468     else if (payload && size)
469     {
470         size_t allocSize = size + CBOR_ENCODING_SIZE_ADDITION;
471
472         outPayload = (uint8_t *)OICCalloc(1, allocSize);
473         VERIFY_NOT_NULL(TAG, outPayload, ERROR);
474         CborEncoder encoder;  // will be initialized in |cbor_parser_init|
475         cbor_encoder_init(&encoder, outPayload, allocSize, 0);
476         CborEncoder resource;  // will be initialized in |cbor_encoder_create_map|
477         cborEncoderResult |= cbor_encoder_create_map(&encoder, &resource, CborIndefiniteLength);
478         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
479
480         cborEncoderResult |= cbor_encode_text_string(&resource, resourceName, strlen(resourceName));
481         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
482         cborEncoderResult |= cbor_encode_byte_string(&resource, payload, size);
483         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
484
485         cborEncoderResult |= cbor_encoder_close_container(&encoder, &resource);
486         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
487         outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
488     }
489
490     ret = WritePayloadToPS(databaseName, outPayload, outSize);
491     VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR);
492
493     OIC_LOG(DEBUG, TAG, "UpdateResourceInPS OUT");
494
495 exit:
496     OICFree(dbData);
497     OICFree(outPayload);
498     OICFree(aclCbor);
499     OICFree(pstatCbor);
500     OICFree(doxmCbor);
501     OICFree(amaclCbor);
502     OICFree(credCbor);
503     OICFree(pconfCbor);
504     OICFree(resetPfCbor);
505     OICFree(crlCbor);
506     OICFree(dpCbor);
507     return ret;
508 }
509
510 /**
511  * Reads the Secure Virtual Database from PS
512  *
513  * @note Caller of this method MUST use OICFree() method to release memory
514  *       referenced by return value.
515  *
516  * @param resourceName is the name of the field for which file content are read.
517  *                     if the value is NULL it will send the content of the whole file.
518  * @param data         is the pointer to the file contents read from the database.
519  * @param size         is the size of the file contents read.
520  *
521  * @return ::OC_STACK_OK for Success, otherwise some error value
522  */
523 OCStackResult GetSecureVirtualDatabaseFromPS(const char *resourceName, uint8_t **data, size_t *size)
524 {
525     return ReadDatabaseFromPS(SVR_DB_DAT_FILE_NAME, resourceName, data, size);
526 }
527
528 /**
529  * This method updates the Secure Virtual Database in PS
530  *
531  * @param resourceName  is the name of the secure resource that will be updated.
532  * @param payload       is the pointer to memory where the CBOR payload is located.
533  * @param size          is the size of the CBOR payload.
534  *
535  * @return ::OC_STACK_OK for Success, otherwise some error value
536  */
537 OCStackResult UpdateSecureResourceInPS(const char *resourceName, const uint8_t *payload, size_t size)
538 {
539     return UpdateResourceInPS(SVR_DB_DAT_FILE_NAME, resourceName, payload, size);
540 }
541
542 /**
543  * Resets the Secure Virtual Resource(s).
544  * This function reads the Reset Profile
545  * and resets the secure virtual resources accordingly.
546  *
547  * @return OCStackResult - result of updating Secure Virtual Resource(s)
548  */
549 OCStackResult ResetSecureResourceInPS(void)
550 {
551     OIC_LOG(DEBUG, TAG, "ResetSecureResourceInPS IN");
552
553     size_t dbSize = 0;
554     size_t outSize = 0;
555     uint8_t *dbData = NULL;
556     uint8_t *outPayload = NULL;
557
558     uint8_t *aclCbor = NULL;
559     uint8_t *credCbor = NULL;
560     uint8_t *pstatCbor = NULL;
561     uint8_t *doxmCbor = NULL;
562     uint8_t *resetPfCbor = NULL;
563
564     int64_t cborEncoderResult = CborNoError;
565     OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
566     if(dbData && dbSize)
567     {
568         size_t aclCborLen = 0;
569         size_t credCborLen = 0;
570         size_t pstatCborLen = 0;
571         size_t doxmCborLen = 0;
572         size_t resetPfCborLen = 0;
573
574         // Gets the reset profile from persistent storage
575         {
576             CborParser parser;  // will be initialized in |cbor_parser_init|
577             CborValue cbor;     // will be initialized in |cbor_parser_init|
578             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
579             CborValue curVal = {0};
580             CborError cborFindResult = CborNoError;
581             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
582             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
583             {
584                 cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
585                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
586             }
587         }
588
589         // Gets each secure virtual resource from the reset profile
590         {
591             CborParser parser;  // will be initialized in |cbor_parser_init|
592             CborValue cbor;     // will be initialized in |cbor_parser_init|
593             cbor_parser_init(resetPfCbor, resetPfCborLen, 0, &parser, &cbor);
594             CborValue curVal = {0};
595             CborError cborFindResult = CborNoError;
596             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
597             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
598             {
599                 cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
600                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
601             }
602             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
603             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
604             {
605                 cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
606                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
607             }
608             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
609             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
610             {
611                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
612                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
613             }
614             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
615             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
616             {
617                 cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
618                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
619             }
620         }
621
622         {
623             size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + resetPfCborLen + CBOR_ENCODING_SIZE_ADDITION;
624
625             outPayload = (uint8_t *) OICCalloc(1, size);
626             VERIFY_NOT_NULL(TAG, outPayload, ERROR);
627             CborEncoder encoder;
628             cbor_encoder_init(&encoder, outPayload, size, 0);
629             CborEncoder secRsrc;
630             cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
631
632             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
633             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
634             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
635             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
636
637             if (credCborLen)
638             {
639                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
640                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Name.");
641                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
642                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Value.");
643             }
644
645             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
646             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
647             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
648             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
649
650             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
651             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Name.");
652             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
653             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Value.");
654
655             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
656             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
657             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
658             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
659
660             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
661             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
662             outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
663         }
664
665         ret = WritePayloadToPS(SVR_DB_DAT_FILE_NAME, outPayload, outSize);
666         VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR);
667     }
668
669     SRMDeInitSecureResources();
670     InitSecureResources();
671     OIC_LOG(DEBUG, TAG, "ResetSecureResourceINPS OUT");
672
673 exit:
674     OICFree(dbData);
675     OICFree(outPayload);
676     OICFree(aclCbor);
677     OICFree(credCbor);
678     OICFree(pstatCbor);
679     OICFree(doxmCbor);
680     OICFree(resetPfCbor);
681     return ret;
682 }
683
684 /**
685  * Creates Reset Profile from the initial secure virtual resources.
686  * This function copies the secure resources
687  * and creates the Reset Profile in the Persistent Storage.
688  * Device ID in doxm and pstat remains as same after reset.
689  *
690  * @return OCStackResult - result of updating Secure Virtual Resource(s)
691  */
692 OCStackResult CreateResetProfile(void)
693 {
694     OIC_LOG(DEBUG, TAG, "CreateResetProfile IN");
695
696     size_t dbSize = 0;
697     uint8_t *dbData = NULL;
698
699     uint8_t *aclCbor = NULL;
700     uint8_t *credCbor = NULL;
701     uint8_t *pstatCbor = NULL;
702     uint8_t *doxmCbor = NULL;
703     uint8_t *resetPfCbor = NULL;
704
705     OCStackResult ret = OC_STACK_ERROR;
706     int64_t cborEncoderResult = CborNoError;
707     ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
708     if (dbData && dbSize)
709     {
710         size_t aclCborLen = 0;
711         size_t credCborLen = 0;
712         size_t pstatCborLen = 0;
713         size_t doxmCborLen = 0;
714         size_t resetPfCborLen = 0;
715
716         {
717             CborParser parser;
718             CborValue cbor;
719             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
720             CborValue curVal = {0};
721             CborError cborFindResult = CborNoError;
722
723             // abort if reset profile exists
724             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
725             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
726             {
727                 OIC_LOG(DEBUG, TAG, "Reset Profile already exists!!");
728                 goto exit;
729             }
730
731             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
732             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
733             {
734                 cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
735                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
736             }
737             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
738             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
739             {
740                 cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
741                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
742             }
743             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
744             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
745             {
746                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
747                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
748             }
749             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
750             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
751             {
752                 cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
753                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult,  "Failed Finding DOXM Name Value.");
754             }
755         }
756
757         {
758             size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + CBOR_ENCODING_SIZE_ADDITION;
759             resetPfCbor = (uint8_t *) OICCalloc(1, size);
760             VERIFY_NOT_NULL(TAG, resetPfCbor, ERROR);
761             CborEncoder encoder;  // will be initialized in |cbor_parser_init|
762             cbor_encoder_init(&encoder, resetPfCbor, size, 0);
763             CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
764             cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
765
766             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
767             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
768             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
769             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
770
771             if (credCborLen)
772             {
773                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
774                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Name.");
775                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
776                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Value.");
777             }
778
779             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
780             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
781             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
782             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
783
784             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
785             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
786             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
787             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
788
789             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
790             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
791             resetPfCborLen = cbor_encoder_get_buffer_size(&encoder, resetPfCbor);
792         }
793
794         UpdateSecureResourceInPS(OIC_JSON_RESET_PF_NAME, resetPfCbor, resetPfCborLen);
795
796     }
797     OIC_LOG(DEBUG, TAG, "CreateResetProfile OUT");
798
799 exit:
800     OICFree(dbData);
801     OICFree(aclCbor);
802     OICFree(credCbor);
803     OICFree(pstatCbor);
804     OICFree(doxmCbor);
805     OICFree(resetPfCbor);
806     return ret;
807 }