Merge branch 'tizen' into tizen_5.5
[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 <unistd.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 "psiutils.h"
42 #include "psinterface.h"
43 #include "doxmresource.h"
44 #include "octhread.h"
45 #include "aclresource.h"
46 #include "credresource.h"
47
48 #define TAG  "OIC_SRM_PSI"
49
50 // SVR database buffer block size
51 #ifdef _WIN32
52 #define DB_FILE_SIZE_BLOCK 1023
53 #else
54 const size_t DB_FILE_SIZE_BLOCK = 1023;
55 #endif
56 //the Secure Virtual Database file size
57 static size_t g_svrDbFileSize = 0;
58 //mutex for the Secure Virtual Database
59 static oc_mutex g_mutexDb = NULL;
60
61 // Persistent Storage status
62 static PSStatus_t g_psStatus = PS_NO_EXTERNAL_DB_SET;
63
64 //SVR DB Validation status
65 static SVRDBValidStatus_t g_svrdbValidStatus = SVRDB_NOT_CHECKED;
66
67 static resetSVRDBCB_t g_resetSVRDBCB = {0};
68
69 resetSVRDBCB_t*  GetResetSVRDBCB(void)
70 {
71     return &g_resetSVRDBCB;
72 }
73
74 /**
75  * Set status of SVR DB after call CheckSVRDBValidity() API
76  */
77 static void SetSVRDBValidStatus(SVRDBValidStatus_t status)
78 {
79      g_svrdbValidStatus = status;
80 }
81
82 /**
83  * Update the Persistent Storage Database size.
84  */
85 void UpdateSizePSI(size_t size)
86 {
87     oc_mutex_lock(g_mutexDb);
88     g_svrDbFileSize = size;
89     oc_mutex_unlock(g_mutexDb);
90 }
91 /**
92  * Init the Persistent Storage Database.
93  */
94 OCStackResult InitPersistentStorageInterface(void)
95 {
96     if (!g_mutexDb)
97     {
98         g_mutexDb = oc_mutex_new();
99         if(!g_mutexDb)
100         {
101             return OC_STACK_ERROR;
102         }
103     }
104
105     UpdateSizePSI(0);
106
107     return OC_STACK_OK;
108 }
109
110 /**
111  * DeInit the Persistent Storage Database.
112  */
113 void DeinitPersistentStorageInterface(void)
114 {
115     g_svrDbFileSize = 0;
116     oc_mutex_free(g_mutexDb);
117     g_mutexDb = NULL;
118 }
119
120 /**
121  * Gets the database size
122  *
123  * @param ps            is a pointer to OCPersistentStorage for the Virtual Resource(s).
124  *
125  * @return size_t - total size of the database
126  */
127 static size_t GetPSIDatabaseSizeWithoutCaching(const OCPersistentStorage *ps)
128 {
129     if (!ps)
130     {
131         return 0;
132     }
133     size_t size = 0;
134     char buffer[DB_FILE_SIZE_BLOCK];  // can not initialize with declaration
135                                       // but maybe not needed to initialize
136     FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
137     if (fp)
138     {
139         size_t bytesRead = 0;
140         do
141         {
142             bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
143             size += bytesRead;
144         } while (bytesRead);
145         ps->close(fp);
146     }
147     return size;
148 }
149
150
151 /**
152  * Gets the the Persistent Storage Database size
153  *
154  * @param ps - pointer of OCPersistentStorage for the Secure Virtual Resource(s)
155  *
156  * @return size_t - total size of the SVR database
157  */
158 static size_t GetPSIDatabaseSize(const OCPersistentStorage *ps)
159 {
160     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
161
162     if (!ps)
163     {
164         return 0;
165     }
166
167     if (!g_svrDbFileSize)
168     {
169         size_t size = 0;
170         char buffer[DB_FILE_SIZE_BLOCK];  // can not initialize with declaration
171                                           // but maybe not needed to initialize
172         FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
173         if (fp)
174         {
175             size_t bytesRead = 0;
176             do
177             {
178                 bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
179                 size += bytesRead;
180             } while (bytesRead);
181             ps->close(fp);
182         }
183         else
184         {
185             OIC_LOG_V(ERROR, TAG, "%s: File open failed.", __func__);
186         }
187
188         UpdateSizePSI(size);
189     }
190     else
191     {
192         OIC_LOG_V(INFO, TAG, "%s get size from cache", __func__);
193     }
194
195     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
196
197     return g_svrDbFileSize;
198 }
199
200 #ifdef __SECURE_PSI__
201 static OCStackResult getPlaintextFromDB(const OCPersistentStorage *ps, uint8_t **pt,
202         size_t *pt_len)
203 {
204     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
205     OCStackResult ret = OC_STACK_ERROR;
206
207     uint8_t *plaintext = NULL;
208
209     FILE *fp = NULL;
210     fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
211     if (NULL == fp)
212     {
213         OIC_LOG(ERROR, TAG, "ps->open() Failed");
214         return OC_STACK_ERROR;
215     }
216
217     // Get fileSize of plaintext
218     char buffer[DB_FILE_SIZE_BLOCK];
219     size_t bytesRead = 0;
220     size_t fileSize = 0;
221     do
222     {
223         bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
224         fileSize += bytesRead;
225     } while (bytesRead);
226
227     // Get plaintext
228     ret = OC_STACK_NO_MEMORY;
229     plaintext = (uint8_t*)OICCalloc(1, fileSize);
230     VERIFY_NON_NULL(TAG, plaintext, ERROR);
231
232     ps->close(fp);
233     fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
234     if (NULL == fp)
235     {
236         OICFree(plaintext);
237         OIC_LOG(ERROR, TAG, "ps->open() Failed");
238         return OC_STACK_ERROR;
239     }
240
241     if (fileSize != ps->read(plaintext, 1, fileSize, fp))
242     {
243         OIC_LOG_V(ERROR, TAG, "ps->read() Failed");
244         ret = OC_STACK_ERROR;
245         goto exit;
246     }
247
248     *pt = plaintext;
249     *pt_len = fileSize;
250     ps->close(fp);
251
252     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
253
254     return OC_STACK_OK;
255 exit:
256     OICFree(plaintext);
257     if (fp)
258     {
259         ps->close(fp);
260     }
261     return ret;
262 }
263
264 static OCStackResult OTEncrypt(const OCPersistentStorage *psForPlain,
265         const OCPersistentStorage *psForEncrypted)
266 {
267     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
268
269     uint8_t *plaintext = NULL;
270     size_t pt_len = 0;
271     OCStackResult ret = getPlaintextFromDB(psForPlain, &plaintext, &pt_len);
272     if (OC_STACK_OK != ret)
273     {
274         OIC_LOG(ERROR, TAG, "getPlaintextFromDB() Failed");
275         return ret;
276     }
277
278     // Encrypt plaintext
279     uint8_t *ciphertext = NULL;
280     size_t ct_len = 0;
281     if (0 != psForEncrypted->encrypt(plaintext, pt_len, &ciphertext, &ct_len))
282     {
283         OIC_LOG(ERROR, TAG, "psForEncrypted->encrypt() Failed");
284         OICFree(plaintext);
285         return OC_STACK_ERROR;
286     }
287     OICFree(plaintext);
288
289     // Write Ciphertext
290     FILE *fp2 = psForEncrypted->open(SVR_DB_DAT_FILE_NAME, "wb");
291     if (NULL == fp2)
292     {
293         OIC_LOG(ERROR, TAG, "psForEncrypted->open() Failed");
294         OICFree(ciphertext);
295         return OC_STACK_ERROR;
296     }
297
298     if (ct_len != psForEncrypted->write(ciphertext, 1, ct_len, fp2))
299     {
300         OIC_LOG(ERROR, TAG, "psForEncrypted->write() Failed");
301         OICFree(ciphertext);
302         return OC_STACK_ERROR;
303     }
304     psForEncrypted->close(fp2);
305
306     // Remove plain DB
307     if (psForPlain->unlink)
308     {
309         psForPlain->unlink(SVR_DB_DAT_FILE_NAME);
310     }
311
312     OICFree(ciphertext);
313     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
314
315     return OC_STACK_OK;
316 }
317
318 OCStackResult setSecurePSI(const unsigned char *key, const OCPersistentStorage *psPlain,
319         const OCPersistentStorage *psEnc, const OCPersistentStorage *psRescue)
320 {
321     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
322
323     if (!key || !psEnc)
324     {
325         OIC_LOG_V(ERROR, TAG, "%s: %s is NULL", __func__, !key ? "key" : "psEnc");
326         return OC_STACK_INVALID_PARAM;
327     }
328     if (!(psEnc->encrypt && psEnc->decrypt))
329     {
330         OIC_LOG(ERROR, TAG, "psEnc->encrypt && psEnc->decrypt should be set");
331         return OC_STACK_INVALID_PARAM;
332     }
333     if (psPlain && !(psPlain->open && psPlain->read && psPlain->close
334                 && psPlain->unlink))
335     {
336         OIC_LOG(ERROR, TAG, "open/read/close/unlink funcion for plain should be set");
337         return OC_STACK_INVALID_PARAM;
338     }
339     if (psRescue && !(psRescue->open && psRescue->read && psRescue->close))
340     {
341         OIC_LOG(ERROR, TAG, "open/read/close funcion for rescue should be set");
342         return OC_STACK_INVALID_PARAM;
343     }
344
345     OCStackResult ret;
346     ret = psiSetKey(key);
347     if (OC_STACK_OK != ret)
348     {
349         OIC_LOG(ERROR, TAG, "psiSetKey() Failed");
350         return ret;
351     }
352     OIC_LOG(DEBUG, TAG, "key is set");
353
354     // if there is new plain db
355     FILE *fp = NULL;
356     if (psPlain && (fp = psPlain->open(SVR_DB_DAT_FILE_NAME, "rb")))
357     {
358         psPlain->close(fp);
359         fp = NULL;
360
361         ret = OTEncrypt(psPlain, psEnc);
362         if (OC_STACK_OK != ret)
363         {
364             OIC_LOG(ERROR, TAG, "OTEncrypt() Failed");
365             return ret;
366         }
367     }
368
369     // check ps & rescue
370     if (psRescue)
371     {
372         ret = CheckPersistentStorage((OCPersistentStorage*)psEnc);
373         if (OC_STACK_OK != ret)
374         {
375             fp = psRescue->open(SVR_DB_DAT_FILE_NAME, "rb");
376             if (NULL == fp)
377             {
378                 OIC_LOG(ERROR, TAG, "psRescue->open() Failed");
379                 return OC_STACK_ERROR;
380             }
381             psRescue->close(fp);
382             fp = NULL;
383
384             ret = OTEncrypt(psRescue, psEnc);
385             if (OC_STACK_OK != ret)
386             {
387                 OIC_LOG_V(ERROR, TAG, "ps is currupted but NOT rescued(%d)", ret);
388                 return ret;
389             }
390             OIC_LOG(INFO, TAG, "ps is currupted and rescued");
391         }
392     }
393
394     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
395
396     return OC_STACK_OK;
397
398 }
399 #endif // __SECURE_PSI__
400
401 /**
402  * Write the Persistent Storage
403  *
404  * @param payload - pointer of payload
405  * @param psize   - size of payload
406  *
407  * @return OCStackResult - OC_STACK_OK sucsess, other - OC_STACK_ERROR
408  */
409 OCStackResult WritePSIDatabase(const uint8_t *payload, size_t size)
410 {
411     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
412
413     if (!payload || !size || !g_mutexDb)
414     {
415         OIC_LOG_V(ERROR, TAG, "%s: %s is NULL",
416                    __func__, !payload ? "payload" : !size ? "size" : "mutex");
417         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
418         return OC_STACK_INVALID_PARAM;
419     }
420
421     OCPersistentStorage *ps = NULL;
422     FILE *fp = NULL;
423     OCStackResult ret = OC_STACK_SVR_DB_NOT_EXIST;
424
425     ps = SRMGetPersistentStorageHandler();
426     VERIFY_NON_NULL(TAG, ps, ERROR);
427
428 #ifdef __SECURE_PSI__
429     if (psiIsKeySet() && ps->encrypt && ps->decrypt)
430     {
431         OIC_LOG(DEBUG, TAG, "ps->encrypt !");
432
433         uint8_t *ciphertext = NULL;
434         size_t ct_len = 0;
435
436         if (0 != ps->encrypt(payload, size, &ciphertext, &ct_len))
437         {
438             OIC_LOG(ERROR, TAG, "ps->encrypt() Failed");
439             ret = OC_STACK_ERROR;
440             goto exit;
441         }
442
443         payload = ciphertext;
444         size = ct_len;
445     }
446 #endif // __SECURE_PSI__
447
448     OIC_LOG_V(INFO, TAG, "Writing in the file: %zu", size);
449
450     fp = ps->open(SVR_DB_DAT_FILE_NAME, "wb");
451     VERIFY_NON_NULL(TAG, fp, ERROR);
452
453     oc_mutex_lock(g_mutexDb);
454     g_svrDbFileSize = ps->write(payload, 1, size, fp);
455     ps->close(fp);
456     oc_mutex_unlock(g_mutexDb);
457
458 #ifdef __SECURE_PSI__
459     if (psiIsKeySet() && ps->encrypt && ps->decrypt)
460     {
461         OICFree((uint8_t*)payload);
462     }
463 #endif // __SECURE_PSI__
464     if (size == g_svrDbFileSize)
465     {
466         OIC_LOG_V(INFO, TAG, "Written %zu bytes into SVR database file", size);
467         ret = OC_STACK_OK;
468     }
469     else
470     {
471         OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", g_svrDbFileSize);
472     }
473
474 exit:
475     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
476     return ret;
477 }
478
479 /**
480  * Gets the Secure Virtual Database from the Persistent Storage
481  *
482  * @param ps - Persistent Storage handler
483  * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
484  * @param data - pointer of the returned Secure Virtual Resource(s)
485  * @param size - pointer of the returned size of Secure Virtual Resource(s)
486  *
487  * @return OCStackResult - result of getting Secure Virtual Resource(s)
488  */
489 OCStackResult GetSecureVirtualDatabaseFromPS2(OCPersistentStorage* ps, const char *rsrcName, uint8_t **data, size_t *size)
490 {
491     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
492
493     if (!data || *data || !size || !ps)
494     {
495         OIC_LOG_V(ERROR, TAG, "%s: %s is NULL",
496                    __func__, !data || *data ? "data" : !size ? "size" : "ps");
497         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
498         return OC_STACK_INVALID_PARAM;
499     }
500
501     FILE *fp = NULL;
502     uint8_t *fsData = NULL;
503     size_t fileSize = 0;
504     OCStackResult ret = OC_STACK_ERROR;
505
506     fileSize = GetPSIDatabaseSizeWithoutCaching(ps);
507     OIC_LOG_V(INFO, TAG, "File Read Size: %zu", fileSize);
508     if (fileSize)
509     {
510         fsData = (uint8_t *) OICCalloc(1, fileSize + 1);
511         VERIFY_NON_NULL(TAG, fsData, ERROR);
512
513         fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
514         VERIFY_NON_NULL(TAG, fp, ERROR);
515         if (ps->read(fsData, 1, fileSize, fp) == fileSize)
516         {
517 #ifdef __SECURE_PSI__
518             if (psiIsKeySet() && ps->encrypt && ps->decrypt)
519             {
520                 OIC_LOG(DEBUG, TAG, "ps->decrypt !");
521
522                 unsigned char *plainData = NULL;
523                 size_t plainSize = 0;
524
525                 if (0 != ps->decrypt(fsData, fileSize, &plainData, &plainSize))
526                 {
527                     OIC_LOG(ERROR, TAG, "ps->decrypt() Failed");
528                     ret = OC_STACK_ERROR;
529                     goto exit;
530                 }
531                 OICFree(fsData);
532                 fsData = plainData;
533                 fileSize = plainSize;
534             }
535 #endif // __SECURE_PSI__
536             if (rsrcName)
537             {
538                 CborParser parser;  // will be initialized in |cbor_parser_init|
539                 CborValue cbor;     // will be initialized in |cbor_parser_init|
540                 cbor_parser_init(fsData, fileSize, 0, &parser, &cbor);
541                 CborValue cborValue = {0};
542                 CborError cborFindResult = cbor_value_map_find_value(&cbor, rsrcName, &cborValue);
543                 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&cborValue))
544                 {
545                     cborFindResult = cbor_value_dup_byte_string(&cborValue, data, size, NULL);
546                     VERIFY_SUCCESS(TAG, CborNoError==cborFindResult, ERROR);
547                     ret = OC_STACK_OK;
548                 }
549                 // in case of |else (...)|, svr_data not found
550             }
551             // return everything in case rsrcName is NULL
552             else
553             {
554                 *size = fileSize;
555                 *data = (uint8_t *) OICCalloc(1, fileSize);
556                 VERIFY_NON_NULL(TAG, *data, ERROR);
557                 memcpy(*data, fsData, fileSize);
558                 ret = OC_STACK_OK;
559             }
560         }
561     }
562     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
563
564 exit:
565     if (fp)
566     {
567         ps->close(fp);
568     }
569     OICFree(fsData);
570     return ret;
571 }
572
573 /**
574  * Gets the Secure Virtual Database from the Persistent Storage
575  *
576  * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
577  * @param data - pointer of the returned Secure Virtual Resource(s)
578  * @param size - pointer of the returned size of Secure Virtual Resource(s)
579  *
580  * @return OCStackResult - result of getting Secure Virtual Resource(s)
581  */
582 OCStackResult GetSecureVirtualDatabaseFromPS(const char *rsrcName, uint8_t **data, size_t *size)
583 {
584     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
585
586     // Logs for Persistent Storage status
587     PrintPSStatus();
588
589     if (!data || *data || !size || !g_mutexDb)
590     {
591         OIC_LOG_V(ERROR, TAG, "%s: %s is NULL",
592                    __func__, !data || *data ? "data" : !size ? "size" : "mutex");
593         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
594         return OC_STACK_INVALID_PARAM;
595     }
596
597     FILE *fp = NULL;
598     uint8_t *fsData = NULL;
599     size_t fileSize = 0;
600     OCStackResult ret = OC_STACK_ERROR;
601
602     OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
603     VERIFY_NON_NULL(TAG, ps, ERROR);
604
605     fileSize = GetPSIDatabaseSize(ps);
606     OIC_LOG_V(INFO, TAG, "File Read Size: %zu", fileSize);
607     if (fileSize)
608     {
609         fsData = (uint8_t *) OICCalloc(1, fileSize);
610         VERIFY_NON_NULL(TAG, fsData, ERROR);
611
612         fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
613         VERIFY_NON_NULL(TAG, fp, ERROR);
614         if (ps->read(fsData, 1, fileSize, fp) == fileSize)
615         {
616 #ifdef __SECURE_PSI__
617             if (psiIsKeySet() && ps->encrypt && ps->decrypt)
618             {
619                 OIC_LOG(DEBUG, TAG, "ps->decrypt !");
620
621                 unsigned char *plainData = NULL;
622                 size_t plainSize = 0;
623
624                 if (0 != ps->decrypt(fsData, fileSize, &plainData, &plainSize))
625                 {
626                     OIC_LOG(ERROR, TAG, "ps->decrypt() Failed");
627                     ret = OC_STACK_ERROR;
628                     goto exit;
629                 }
630                 OICFree(fsData);
631                 fsData = plainData;
632                 fileSize = plainSize;
633             }
634 #endif // __SECURE_PSI__
635             if (rsrcName)
636             {
637                 CborParser parser;  // will be initialized in |cbor_parser_init|
638                 CborValue cbor;     // will be initialized in |cbor_parser_init|
639                 cbor_parser_init(fsData, fileSize, 0, &parser, &cbor);
640                 CborValue cborValue = {0};
641                 CborError cborFindResult = cbor_value_map_find_value(&cbor, rsrcName, &cborValue);
642                 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&cborValue))
643                 {
644                     cborFindResult = cbor_value_dup_byte_string(&cborValue, data, size, NULL);
645                     VERIFY_SUCCESS(TAG, CborNoError==cborFindResult, ERROR);
646                     ret = OC_STACK_OK;
647                 }
648                 // in case of |else (...)|, svr_data not found
649             }
650             // return everything in case rsrcName is NULL
651             else
652             {
653                 *size = fileSize;
654                 *data = (uint8_t *) OICCalloc(1, fileSize);
655                 VERIFY_NON_NULL(TAG, *data, ERROR);
656                 memcpy(*data, fsData, fileSize);
657                 ret = OC_STACK_OK;
658             }
659         }
660     }
661     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
662
663 exit:
664     if (fp)
665     {
666         ps->close(fp);
667     }
668     OICFree(fsData);
669     return ret;
670 }
671
672 /**
673  * Updates the Secure Virtual Resource(s) into the Persistent Storage.
674  * This function stores cbor-payload of each resource by appending resource name,
675  * and empty payload implies deleting the value
676  *
677  * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
678  * @param psPayload - pointer of the updated Secure Virtual Resource(s)
679  * @param psSize - the updated size of Secure Virtual Resource(s)
680  *
681  * @return OCStackResult - result of updating Secure Virtual Resource(s)
682  */
683 OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPayload, size_t psSize)
684 {
685     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
686
687     if (!rsrcName)
688     {
689         return OC_STACK_INVALID_PARAM;
690     }
691
692     size_t dbSize = 0;
693     size_t outSize = 0;
694     uint8_t *dbData = NULL;
695     uint8_t *outPayload = NULL;
696
697     uint8_t *aclCbor = NULL;
698     uint8_t *pstatCbor = NULL;
699     uint8_t *doxmCbor = NULL;
700     uint8_t *amaclCbor = NULL;
701     uint8_t *credCbor = NULL;
702     uint8_t *pconfCbor = NULL;
703     uint8_t *resetPfCbor = NULL;
704     uint8_t *crlCbor = NULL;
705
706     int64_t cborEncoderResult = CborNoError;
707     OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
708     if (OC_STACK_OK != ret)
709     {
710         OIC_LOG_V(ERROR, TAG, "GetSecureVirtualDatabaseFromPS() is failed(%d)", ret);
711     }
712     if (dbData && dbSize)
713     {
714         size_t aclCborLen = 0;
715         size_t pstatCborLen = 0;
716         size_t doxmCborLen = 0;
717         size_t amaclCborLen = 0;
718         size_t credCborLen = 0;
719         size_t pconfCborLen = 0;
720         size_t resetPfCborLen = 0;
721         size_t crlCborLen = 0;
722
723         ret = OC_STACK_ERROR;
724
725         // Gets each secure virtual resource from persistent storage
726         // this local scoping intended, for destroying large cbor instances after use
727         {
728             CborParser parser;  // will be initialized in |cbor_parser_init|
729             CborValue cbor;     // will be initialized in |cbor_parser_init|
730             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
731             CborValue curVal = {0};
732             CborError cborFindResult = CborNoError;
733
734             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
735             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
736             {
737                 cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
738                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
739             }
740             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
741             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
742             {
743                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
744                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
745             }
746             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
747             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
748             {
749                 cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
750                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult,  "Failed Finding DOXM Name Value.");
751             }
752             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_AMACL_NAME, &curVal);
753             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
754             {
755                 cborFindResult = cbor_value_dup_byte_string(&curVal, &amaclCbor, &amaclCborLen, NULL);
756                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMACL Name Value.");
757             }
758
759             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
760             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
761             {
762                 cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
763                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
764             }
765             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PCONF_NAME, &curVal);
766             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
767             {
768                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
769                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
770             }
771             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
772             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
773             {
774                 cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
775                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
776             }
777             int64_t cborFindCrlResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRL_NAME, &curVal);
778             if (CborNoError == cborFindCrlResult && cbor_value_is_byte_string(&curVal))
779             {
780                 cborFindCrlResult = cbor_value_dup_byte_string(&curVal, &crlCbor, &crlCborLen, NULL);
781                 if (CborNoError != cborFindCrlResult && CborErrorOutOfMemory != cborFindCrlResult)
782                 {
783                     OIC_LOG(ERROR, TAG, "Failed Finding optional CRL Name Value.");
784                 }
785                 else
786                 {
787                     OIC_LOG(INFO, TAG, "Successfully Finding optional CRL Name Value.");
788                 }
789             }
790         }
791
792         // Updates the added |psPayload| with the existing secure virtual resource(s)
793         // this local scoping intended, for destroying large cbor instances after use
794         {
795             size_t size = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
796                         + credCborLen + pconfCborLen + resetPfCborLen + crlCborLen
797                         + psSize + 255;
798             // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
799
800             outPayload = (uint8_t *) OICCalloc(1, size);
801             VERIFY_NON_NULL(TAG, outPayload, ERROR);
802             CborEncoder encoder;  // will be initialized in |cbor_parser_init|
803             cbor_encoder_init(&encoder, outPayload, size, 0);
804             CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
805             cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
806             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
807
808             if (psPayload && psSize)
809             {
810                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, rsrcName, strlen(rsrcName));
811                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
812                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, psPayload, psSize);
813                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
814             }
815             if (strcmp(OIC_JSON_ACL_NAME, rsrcName) && aclCborLen)
816             {
817                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
818                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
819                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
820                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
821             }
822             if (strcmp(OIC_JSON_PSTAT_NAME, rsrcName) && pstatCborLen)
823             {
824                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
825                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
826                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
827                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
828             }
829             if (strcmp(OIC_JSON_DOXM_NAME, rsrcName) && doxmCborLen)
830             {
831                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
832                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
833                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
834                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
835             }
836             if (strcmp(OIC_JSON_AMACL_NAME, rsrcName) && amaclCborLen)
837             {
838                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME));
839                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Name.");
840                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, amaclCbor, amaclCborLen);
841                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Value.");
842             }
843             if (strcmp(OIC_JSON_CRED_NAME, rsrcName) && credCborLen)
844             {
845                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
846                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Name.");
847                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
848                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Value.");
849             }
850             if (strcmp(OIC_JSON_PCONF_NAME, rsrcName) && pconfCborLen)
851             {
852                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PCONF_NAME, strlen(OIC_JSON_PCONF_NAME));
853                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Name.");
854                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pconfCbor, pconfCborLen);
855                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
856             }
857             if (strcmp(OIC_JSON_RESET_PF_NAME, rsrcName) && resetPfCborLen)
858             {
859                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
860                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
861                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
862                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
863             }
864             if (strcmp(OIC_JSON_CRL_NAME, rsrcName) && crlCborLen)
865             {
866                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRL_NAME, strlen(OIC_JSON_CRL_NAME));
867                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Name.");
868                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, crlCbor, crlCborLen);
869                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Crl Value.");
870             }
871
872             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
873             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
874             outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
875         }
876     }
877     else if (psPayload && psSize)
878     {
879         size_t size = psSize + 255;
880         // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
881
882         outPayload = (uint8_t *) OICCalloc(1, size);
883         VERIFY_NON_NULL(TAG, outPayload, ERROR);
884         CborEncoder encoder;  // will be initialized in |cbor_parser_init|
885         cbor_encoder_init(&encoder, outPayload, size, 0);
886         CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
887         cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
888         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
889
890         cborEncoderResult |= cbor_encode_text_string(&secRsrc, rsrcName, strlen(rsrcName));
891         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
892         cborEncoderResult |= cbor_encode_byte_string(&secRsrc, psPayload, psSize);
893         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
894
895         cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
896         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
897         outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
898     }
899
900     ret = WritePSIDatabase(outPayload, outSize);
901     if (OC_STACK_OK != ret)
902     {
903         OIC_LOG_V(ERROR, TAG, "WritePSIDatabase() is failed(%d)", ret);
904     }
905     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
906
907 exit:
908     OICFree(dbData);
909     OICFree(outPayload);
910     OICFree(aclCbor);
911     OICFree(pstatCbor);
912     OICFree(doxmCbor);
913     OICFree(amaclCbor);
914     OICFree(credCbor);
915     OICFree(pconfCbor);
916     OICFree(resetPfCbor);
917     OICFree(crlCbor);
918     return ret;
919 }
920
921 /**
922  * Resets the Secure Virtual Resource(s).
923  * This function reads the Reset Profile
924  * and resets the secure virtual resources accordingly.
925  *
926  * @return OCStackResult - result of updating Secure Virtual Resource(s)
927  */
928 OCStackResult ResetSecureResourceInPS(void)
929 {
930     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
931
932     size_t dbSize = 0;
933     size_t outSize = 0;
934     uint8_t *dbData = NULL;
935     uint8_t *outPayload = NULL;
936
937     uint8_t *aclCbor = NULL;
938     uint8_t *credCbor = NULL;
939     uint8_t *pstatCbor = NULL;
940     uint8_t *doxmCbor = NULL;
941     uint8_t *resetPfCbor = NULL;
942
943     int64_t cborEncoderResult = CborNoError;
944     OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
945     if (OC_STACK_OK != ret)
946     {
947         OIC_LOG_V(ERROR, TAG, "GetSecureVirtualDatabaseFromPS() is failed(%d)", ret);
948     }
949     if(dbData && dbSize)
950     {
951         size_t aclCborLen = 0;
952         size_t credCborLen = 0;
953         size_t pstatCborLen = 0;
954         size_t doxmCborLen = 0;
955         size_t resetPfCborLen = 0;
956
957         ret = OC_STACK_ERROR;
958
959         // Gets the reset profile from persistent storage
960         {
961             CborParser parser;  // will be initialized in |cbor_parser_init|
962             CborValue cbor;     // will be initialized in |cbor_parser_init|
963             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
964             CborValue curVal = {0};
965             CborError cborFindResult = CborNoError;
966             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
967             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
968             {
969                 cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
970                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
971             }
972             else if (CborNoError == cborFindResult && CborInvalidType == curVal.type)
973             {
974                 OIC_LOG(ERROR, TAG, "resetpf is not found");
975                 goto exit;
976             }
977             else
978             {
979                 OIC_LOG_V(ERROR, TAG, "cbor_value_map_find_value() Failed(%d)",
980                         cborFindResult);
981                 goto exit;
982             }
983         }
984
985         // Gets each secure virtual resource from the reset profile
986         {
987             CborParser parser;  // will be initialized in |cbor_parser_init|
988             CborValue cbor;     // will be initialized in |cbor_parser_init|
989             cbor_parser_init(resetPfCbor, resetPfCborLen, 0, &parser, &cbor);
990             CborValue curVal = {0};
991             CborError cborFindResult = CborNoError;
992             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
993             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
994             {
995                 cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
996                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
997             }
998             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
999             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1000             {
1001                 cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
1002                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
1003             }
1004             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
1005             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1006             {
1007                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
1008                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
1009             }
1010             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
1011             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1012             {
1013                 cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
1014                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
1015             }
1016         }
1017
1018         {
1019             size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + resetPfCborLen + 255;
1020             // This added '255' is arbitrary value added to cover the name of the resource, map addition, and ending
1021
1022             outPayload = (uint8_t *) OICCalloc(1, size);
1023             VERIFY_NON_NULL(TAG, outPayload, ERROR);
1024             CborEncoder encoder;
1025             cbor_encoder_init(&encoder, outPayload, size, 0);
1026             CborEncoder secRsrc;
1027             cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
1028
1029             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
1030             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
1031             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
1032             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
1033
1034             if (credCborLen)
1035             {
1036                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
1037                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Name.");
1038                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
1039                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Value.");
1040             }
1041
1042             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
1043             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
1044             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
1045             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
1046
1047             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
1048             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Name.");
1049             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
1050             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Value.");
1051
1052             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
1053             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
1054             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
1055             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
1056
1057             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
1058             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
1059             outSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
1060         }
1061
1062         ret = WritePSIDatabase(outPayload, outSize);
1063         if (OC_STACK_OK != ret)
1064         {
1065             OIC_LOG_V(ERROR, TAG, "WritePSIDatabase() is failed(%d)", ret);
1066         }
1067     }
1068
1069     SRMDeInitSecureResources();
1070     InitSecureResources();
1071     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1072
1073 exit:
1074     OICFree(dbData);
1075     OICFree(outPayload);
1076     OICFree(aclCbor);
1077     OICFree(credCbor);
1078     OICFree(pstatCbor);
1079     OICFree(doxmCbor);
1080     OICFree(resetPfCbor);
1081
1082     if (NULL != g_resetSVRDBCB.callback)
1083     {
1084         g_resetSVRDBCB.callback(ret);
1085     }
1086     else
1087     {
1088         OIC_LOG_V(DEBUG, TAG, "%s - Notifier resetSVRDB callback isn't registered.", __func__);
1089     }
1090
1091     return ret;
1092 }
1093
1094 /**
1095  * Creates Reset Profile from the initial secure virtual resources.
1096  * This function copies the secure resources
1097  * and creates the Reset Profile in the Persistent Storage.
1098  * Device ID in doxm and pstat remains as same after reset.
1099  *
1100  * @return OCStackResult - result of updating Secure Virtual Resource(s)
1101  */
1102 OCStackResult CreateResetProfile(void)
1103 {
1104     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1105
1106     size_t dbSize = 0;
1107     uint8_t *dbData = NULL;
1108
1109     uint8_t *aclCbor = NULL;
1110     uint8_t *credCbor = NULL;
1111     uint8_t *pstatCbor = NULL;
1112     uint8_t *doxmCbor = NULL;
1113     uint8_t *resetPfCbor = NULL;
1114
1115     OCStackResult ret = OC_STACK_ERROR;
1116     int64_t cborEncoderResult = CborNoError;
1117     ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
1118     if (OC_STACK_OK != ret)
1119     {
1120         OIC_LOG_V(ERROR, TAG, "GetSecureVirtualDatabaseFromPS() is failed(%d)", ret);
1121     }
1122     if (dbData && dbSize)
1123     {
1124         size_t aclCborLen = 0;
1125         size_t credCborLen = 0;
1126         size_t pstatCborLen = 0;
1127         size_t doxmCborLen = 0;
1128         size_t resetPfCborLen = 0;
1129
1130         ret = OC_STACK_ERROR;
1131         {
1132             CborParser parser;
1133             CborValue cbor;
1134             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
1135             CborValue curVal = {0};
1136             CborError cborFindResult = CborNoError;
1137
1138             // abort if reset profile exists
1139             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
1140             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1141             {
1142                 OIC_LOG(DEBUG, TAG, "Reset Profile already exists!!");
1143                 OICFree(dbData);
1144                 return OC_STACK_OK;
1145             }
1146
1147             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
1148             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1149             {
1150                 cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
1151                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
1152             }
1153             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
1154             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1155             {
1156                 cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
1157                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
1158             }
1159             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
1160             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1161             {
1162                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
1163                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
1164             }
1165             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
1166             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1167             {
1168                 cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
1169                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult,  "Failed Finding DOXM Name Value.");
1170             }
1171         }
1172
1173         {
1174             size_t size = aclCborLen + credCborLen + pstatCborLen + doxmCborLen + 255;
1175             resetPfCbor = (uint8_t *) OICCalloc(1, size);
1176             VERIFY_NON_NULL(TAG, resetPfCbor, ERROR);
1177             CborEncoder encoder;  // will be initialized in |cbor_parser_init|
1178             cbor_encoder_init(&encoder, resetPfCbor, size, 0);
1179             CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
1180             cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
1181
1182             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
1183             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
1184             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
1185             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
1186
1187             if (credCborLen)
1188             {
1189                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
1190                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Name.");
1191                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
1192                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Value.");
1193             }
1194
1195             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
1196             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
1197             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
1198             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
1199
1200             cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
1201             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
1202             cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
1203             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
1204
1205             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
1206             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
1207             resetPfCborLen = cbor_encoder_get_buffer_size(&encoder, resetPfCbor);
1208         }
1209
1210         ret = UpdateSecureResourceInPS(OIC_JSON_RESET_PF_NAME, resetPfCbor, resetPfCborLen);
1211         if (OC_STACK_OK != ret)
1212         {
1213             OIC_LOG(ERROR, TAG, "Error in UpdateSecureResourceInPS");
1214         }
1215
1216     }
1217     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1218
1219 exit:
1220     OICFree(dbData);
1221     OICFree(aclCbor);
1222     OICFree(credCbor);
1223     OICFree(pstatCbor);
1224     OICFree(doxmCbor);
1225     OICFree(resetPfCbor);
1226     return ret;
1227 }
1228
1229 void SetPSStatus(PSStatus_t status)
1230 {
1231     g_psStatus = status;
1232 }
1233
1234 SVRDBValidStatus_t GetSVRDBValidStatus()
1235 {
1236     return g_svrdbValidStatus;
1237 }
1238
1239 void PrintPSStatus(void)
1240 {
1241     switch(g_psStatus)
1242     {
1243         case PS_NORMAL:
1244             OIC_LOG(INFO, TAG, "PS Status: Normal - using external DB");
1245             break;
1246         case PS_OPEN_FAIL:
1247             OIC_LOG(INFO, TAG, "PS Status: Failed to open external DB! - using default DB");
1248             break;
1249         case PS_PARSE_FAIL:
1250             OIC_LOG(INFO, TAG, "PS Status: Failed to CBOR parse external DB! - using default DB");
1251             break;
1252         default:
1253             OIC_LOG(INFO, TAG, "PS Status: No external DB set - using internal memory");
1254
1255     }
1256 }
1257
1258 OCStackResult CheckSVRDBValidity(void)
1259 {
1260     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1261
1262     OCStackResult res = OC_STACK_ERROR;
1263     OicUuid_t emptyUuid = OC_DEFAULT_OICUUID;
1264     OicUuid_t devOwnerUuid = OC_DEFAULT_OICUUID;
1265     OicUuid_t devRownerUuid = OC_DEFAULT_OICUUID;
1266     OicUuid_t resRowneruuid = OC_DEFAULT_OICUUID;
1267     bool isDevOwnerUuidEmpty = false;
1268     bool isDevRownerUuidEmpty = false;
1269     bool isPstatRownerUuidEmpty = false;
1270     bool isAclRownerUuidEmpty = false;
1271     bool isCredRownerUuidEmpty = false;
1272     OicSecDpm_t cm = NORMAL;
1273
1274     bool isOwned = false;
1275     res = GetDoxmIsOwned(&isOwned);
1276
1277     if( OC_STACK_OK != res)
1278     {
1279         OIC_LOG_V(ERROR, TAG, "%s - doxm is NULL!", __func__);
1280         goto exit;
1281     }
1282
1283     if(OC_STACK_OK != GetDoxmDevOwnerId(&devOwnerUuid) ||
1284         OC_STACK_OK != GetDoxmRownerId(&devRownerUuid))
1285     {
1286         res = OC_STACK_ERROR;
1287         goto exit;
1288     }
1289
1290     if (0 == memcmp(&devOwnerUuid, &emptyUuid, sizeof(devOwnerUuid)))
1291     {
1292         isDevOwnerUuidEmpty = true;
1293     }
1294     else
1295     {
1296         isDevOwnerUuidEmpty = false;
1297     }
1298
1299     if (0 == memcmp(&devRownerUuid, &emptyUuid, sizeof(devRownerUuid)))
1300     {
1301         isDevRownerUuidEmpty = true;
1302     }
1303     else
1304     {
1305         isDevRownerUuidEmpty = false;
1306     }
1307
1308     if (OC_STACK_OK != GetPstatRownerId(&resRowneruuid))
1309    {
1310         res = OC_STACK_ERROR;
1311         goto exit;
1312     }
1313
1314     if (0 == memcmp(&resRowneruuid, &emptyUuid, sizeof(resRowneruuid)))
1315     {
1316         isPstatRownerUuidEmpty = true;
1317     }
1318     else
1319     {
1320         isPstatRownerUuidEmpty = false;
1321     }
1322
1323     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetPstatCm(&cm), ERROR);
1324
1325     if (OC_STACK_OK != GetAclRownerId(&resRowneruuid))
1326    {
1327         res = OC_STACK_ERROR;
1328         goto exit;
1329     }
1330
1331     if (0 == memcmp(&resRowneruuid, &emptyUuid, sizeof(resRowneruuid)))
1332     {
1333         isAclRownerUuidEmpty = true;
1334     }
1335     else
1336     {
1337         isAclRownerUuidEmpty = false;
1338     }
1339
1340     if (OC_STACK_OK != GetCredRownerId(&resRowneruuid))
1341    {
1342         res = OC_STACK_ERROR;
1343         goto exit;
1344     }
1345
1346     if (0 == memcmp(&resRowneruuid, &emptyUuid, sizeof(resRowneruuid)))
1347     {
1348         isCredRownerUuidEmpty = true;
1349     }
1350     else
1351     {
1352         isCredRownerUuidEmpty = false;
1353     }
1354
1355     if(true == isOwned)
1356     {
1357         if ( isDevOwnerUuidEmpty ||isDevRownerUuidEmpty )
1358         {
1359             OIC_LOG_V(ERROR, TAG, "%s - uuid is empty for owned device!", __func__);
1360             res = OC_STACK_ERROR;
1361             goto exit;
1362        }
1363
1364        if(!GetPstatIsop() || (cm & TAKE_OWNER))
1365        {
1366             OIC_LOG_V(ERROR, TAG, "%s - isop or cm properties are incorrect!", __func__);
1367             res = OC_STACK_ERROR;
1368             goto exit;
1369        }
1370
1371        if (isPstatRownerUuidEmpty)
1372        {
1373             OIC_LOG_V(ERROR, TAG, "%s - pstatRownerUuid is empty for owned device!", __func__);
1374             res = OC_STACK_ERROR;;
1375             goto exit;
1376        }
1377
1378        if (isAclRownerUuidEmpty)
1379        {
1380             OIC_LOG_V(ERROR, TAG, "%s - aclRownerUuid is empty for owned device!", __func__);
1381             res = OC_STACK_ERROR;
1382             goto exit;
1383        }
1384
1385         if (isCredRownerUuidEmpty)
1386        {
1387             OIC_LOG_V(ERROR, TAG, "%s - credRownerUuid is empty for owned device!", __func__);
1388             res = OC_STACK_ERROR;
1389             goto exit;
1390        }
1391
1392         if (OC_STACK_OK != CheckSecurityACEPermission(PERMISSION_READ))
1393         {
1394             OIC_LOG_V(ERROR, TAG, "%s - ACE permission doesn't match to READ", __func__);
1395             res = OC_STACK_ERROR;
1396             goto exit;
1397         }
1398     }
1399     else
1400     {
1401         if ( !isDevOwnerUuidEmpty ||!isDevRownerUuidEmpty )
1402         {
1403             OIC_LOG_V(ERROR, TAG, "%s - uuid is not empty for unOwned device!", __func__);
1404             res = OC_STACK_ERROR;
1405             goto exit;
1406        }
1407
1408         if (!isPstatRownerUuidEmpty)
1409         {
1410             OIC_LOG_V(ERROR, TAG, "%s - pstatRownerUuid is not empty for unOwned device!", __func__);
1411             res = OC_STACK_ERROR;
1412              goto exit;
1413         }
1414
1415        if(GetPstatIsop() || !(cm  & TAKE_OWNER))
1416        {
1417             res = OC_STACK_ERROR;
1418             goto exit;
1419        }
1420
1421        if (!isAclRownerUuidEmpty)
1422        {
1423             OIC_LOG_V(ERROR, TAG, "%s - aclRownerUuid is not empty for unOwned device!", __func__);
1424             res = OC_STACK_ERROR;
1425             goto exit;
1426        }
1427
1428         if (!isCredRownerUuidEmpty)
1429        {
1430             OIC_LOG_V(ERROR, TAG, "%s - credRownerUuid is not empty for unOwned device!", __func__);
1431             res = OC_STACK_ERROR;
1432             goto exit;
1433        }
1434
1435        if (OC_STACK_OK != CheckSecurityACEPermission(PERMISSION_READ | PERMISSION_WRITE))
1436        {
1437             OIC_LOG_V(ERROR, TAG, "%s - ACE permission doesn't match to READ|WRITE", __func__);
1438             res = OC_STACK_ERROR;
1439             goto exit;
1440        }
1441
1442     }
1443     res = OC_STACK_OK;
1444
1445     exit:
1446
1447         if (OC_STACK_OK != res)
1448         {
1449             if (isResetPFExist() && !isOwned)
1450             {
1451                 res = ResetSecureResourceInPS();
1452                 OIC_LOG_V(INFO, TAG, "%s - Secure resources reseted (%d)",  __func__, res);
1453             }
1454             else
1455             {
1456                 res = OC_STACK_INCONSISTENT_DB;
1457             }
1458         }
1459
1460     if(OC_STACK_OK == res)
1461     {
1462         SetSVRDBValidStatus(SVRDB_VALID);
1463     }
1464     else
1465     {
1466         SetSVRDBValidStatus(SVRDB_NOT_VALID);
1467     }
1468     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1469
1470     return res;
1471 }
1472
1473 bool isResetPFExist(void)
1474 {
1475     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1476
1477     bool ret = false;
1478     size_t dbSize = 0;
1479     uint8_t *dbData = NULL;
1480
1481     OCStackResult ocRes = OC_STACK_ERROR;
1482
1483     ocRes = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
1484     if (OC_STACK_OK != ocRes)
1485     {
1486         OIC_LOG_V(ERROR, TAG, "GetSecureVirtualDatabaseFromPS() is failed(%d)", ocRes);
1487     }
1488     if (dbData && dbSize)
1489     {
1490         ocRes = OC_STACK_ERROR;
1491         {
1492             CborParser parser = OC_DEFAULT_CBOR_PARSER;
1493             CborValue cbor = OC_DEFAULT_CBOR_VALUE;
1494             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
1495             CborValue curVal = OC_DEFAULT_CBOR_VALUE;
1496             CborError cborFindResult = CborNoError;
1497
1498             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
1499             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
1500             {
1501                 OIC_LOG(DEBUG, TAG, "Reset Profile already exists!");
1502                 ret = true;
1503             }
1504             else
1505             {
1506                 OIC_LOG(DEBUG, TAG, "Reset Profile doesn't exists!");
1507                 ret = false;
1508             }
1509         }
1510     }
1511     OICFree(dbData);
1512     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1513
1514     return ret;
1515 }