Merge branch '1.1-rel'
[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
28 #include "cainterface.h"
29 #include "logger.h"
30 #include "ocpayload.h"
31 #include "ocpayloadcbor.h"
32 #include "ocstack.h"
33 #include "oic_malloc.h"
34 #include "payload_logging.h"
35 #include "resourcemanager.h"
36 #include "secureresourcemanager.h"
37 #include "srmresourcestrings.h"
38 #include "srmutility.h"
39
40 #define TAG  "SRM-PSI"
41
42 //SVR database buffer block size
43 const size_t DB_FILE_SIZE_BLOCK = 1023;
44
45 /**
46  * Gets the Secure Virtual Database size
47  *
48  * @param ps - pointer of OCPersistentStorage for the Secure Virtual Resource(s)
49  *
50  * @return size_t - total size of the SVR database
51  */
52 static size_t GetSVRDatabaseSize(const OCPersistentStorage *ps)
53 {
54     if (!ps)
55     {
56         return 0;
57     }
58     size_t size = 0;
59     char buffer[DB_FILE_SIZE_BLOCK];  // can not initialize with declaration
60                                       // but maybe not needed to initialize
61     FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
62     if (fp)
63     {
64         size_t bytesRead = 0;
65         do
66         {
67             bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
68             size += bytesRead;
69         } while (bytesRead);
70         ps->close(fp);
71     }
72     return size;
73 }
74
75 /**
76  * Gets the Secure Virtual Database from the Persistent Storage
77  *
78  * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
79  * @param data - pointer of the returned Secure Virtual Resource(s)
80  * @param size - pointer of the returned size of Secure Virtual Resource(s)
81  *
82  * @return OCStackResult - result of getting Secure Virtual Resource(s)
83  */
84 OCStackResult GetSecureVirtualDatabaseFromPS(const char *rsrcName, uint8_t **data, size_t *size)
85 {
86     OIC_LOG(DEBUG, TAG, "GetSecureVirtualDatabaseFromPS IN");
87     if (!data || *data || !size)
88     {
89         return OC_STACK_INVALID_PARAM;
90     }
91
92     FILE *fp = NULL;
93     uint8_t *fsData = NULL;
94     size_t fileSize = 0;
95     OCStackResult ret = OC_STACK_ERROR;
96
97     OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
98     VERIFY_NON_NULL(TAG, ps, ERROR);
99
100     fileSize = GetSVRDatabaseSize(ps);
101     OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
102     if (fileSize)
103     {
104         fsData = (uint8_t *) OICCalloc(1, fileSize);
105         VERIFY_NON_NULL(TAG, fsData, ERROR);
106
107         fp = ps->open(SVR_DB_DAT_FILE_NAME, "rb");
108         VERIFY_NON_NULL(TAG, fp, ERROR);
109         if (ps->read(fsData, 1, fileSize, fp) == fileSize)
110         {
111             if (rsrcName)
112             {
113                 CborParser parser;  // will be initialized in |cbor_parser_init|
114                 CborValue cbor;     // will be initialized in |cbor_parser_init|
115                 cbor_parser_init(fsData, fileSize, 0, &parser, &cbor);
116                 CborValue cborValue = {0};
117                 CborError cborFindResult = cbor_value_map_find_value(&cbor, rsrcName, &cborValue);
118                 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&cborValue))
119                 {
120                     cborFindResult = cbor_value_dup_byte_string(&cborValue, data, size, NULL);
121                     VERIFY_SUCCESS(TAG, CborNoError==cborFindResult, ERROR);
122                     ret = OC_STACK_OK;
123                 }
124                 // in case of |else (...)|, svr_data not found
125             }
126             // return everything in case rsrcName is NULL
127             else
128             {
129                 *size = fileSize;
130                 *data = (uint8_t *) OICCalloc(1, fileSize);
131                 VERIFY_NON_NULL(TAG, *data, ERROR);
132                 memcpy(*data, fsData, fileSize);
133                 ret = OC_STACK_OK;
134             }
135         }
136     }
137     OIC_LOG(DEBUG, TAG, "GetSecureVirtualDatabaseFromPS OUT");
138
139 exit:
140     if (fp)
141     {
142         ps->close(fp);
143     }
144     OICFree(fsData);
145     return ret;
146 }
147
148 /**
149  * Updates the Secure Virtual Resource(s) into the Persistent Storage.
150  * This function stores cbor-payload of each resource by appending resource name,
151  * and empty payload implies deleting the value
152  *
153  * @param rsrcName - pointer of character string for the SVR name (e.g. "acl")
154  * @param psPayload - pointer of the updated Secure Virtual Resource(s)
155  * @param psSize - the updated size of Secure Virtual Resource(s)
156  *
157  * @return OCStackResult - result of updating Secure Virtual Resource(s)
158  */
159 OCStackResult UpdateSecureResourceInPS(const char *rsrcName, const uint8_t *psPayload, size_t psSize)
160 {
161     OIC_LOG(DEBUG, TAG, "UpdateSecureResourceInPS IN");
162     if (!rsrcName)
163     {
164         return OC_STACK_INVALID_PARAM;
165     }
166
167     size_t dbSize = 0;
168     size_t outSize = 0;
169     uint8_t *dbData = NULL;
170     uint8_t *outPayload = NULL;
171
172     uint8_t *aclCbor = NULL;
173     uint8_t *pstatCbor = NULL;
174     uint8_t *doxmCbor = NULL;
175     uint8_t *amaclCbor = NULL;
176     uint8_t *svcCbor = NULL;
177     uint8_t *credCbor = NULL;
178     uint8_t *pconfCbor = NULL;
179
180     int64_t cborEncoderResult = CborNoError;
181     OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
182     if (dbData && dbSize)
183     {
184         size_t aclCborLen = 0;
185         size_t pstatCborLen = 0;
186         size_t doxmCborLen = 0;
187         size_t amaclCborLen = 0;
188         size_t svcCborLen = 0;
189         size_t credCborLen = 0;
190         size_t pconfCborLen = 0;
191
192         // Gets each secure virtual resource from persistent storage
193         // this local scoping intended, for destroying large cbor instances after use
194         {
195             CborParser parser;  // will be initialized in |cbor_parser_init|
196             CborValue cbor;     // will be initialized in |cbor_parser_init|
197             cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
198             CborValue curVal = {0};
199             CborError cborFindResult = CborNoError;
200
201             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
202             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
203             {
204                 cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
205                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
206             }
207             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
208             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
209             {
210                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
211                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
212             }
213             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
214             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
215             {
216                 cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
217                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult,  "Failed Finding DOXM Name Value.");
218             }
219             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_AMACL_NAME, &curVal);
220             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
221             {
222                 cborFindResult = cbor_value_dup_byte_string(&curVal, &amaclCbor, &amaclCborLen, NULL);
223                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding AMACL Name Value.");
224             }
225             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_SVC_NAME, &curVal);
226             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
227             {
228                 cborFindResult = cbor_value_dup_byte_string(&curVal, &svcCbor, &svcCborLen, NULL);
229                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SVC Name Value.");
230             }
231             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_CRED_NAME, &curVal);
232             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
233             {
234                 cborFindResult = cbor_value_dup_byte_string(&curVal, &credCbor, &credCborLen, NULL);
235                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CRED Name Value.");
236             }
237             cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PCONF_NAME, &curVal);
238             if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
239             {
240                 cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
241                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
242             }
243         }
244
245         // Updates the added |psPayload| with the existing secure virtual resource(s)
246         // this local scoping intended, for destroying large cbor instances after use
247         {
248             size_t size = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
249                         + svcCborLen + credCborLen + pconfCborLen + psSize + 255;
250             // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
251
252             outPayload = (uint8_t *) OICCalloc(1, size);
253             VERIFY_NON_NULL(TAG, outPayload, ERROR);
254             CborEncoder encoder;  // will be initialized in |cbor_parser_init|
255             cbor_encoder_init(&encoder, outPayload, size, 0);
256             CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
257             cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
258             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
259
260             if (psPayload && psSize)
261             {
262                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, rsrcName, strlen(rsrcName));
263                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
264                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, psPayload, psSize);
265                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
266             }
267             if (strcmp(OIC_JSON_ACL_NAME, rsrcName) && aclCborLen)
268             {
269                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
270                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
271                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
272                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
273             }
274             if (strcmp(OIC_JSON_PSTAT_NAME, rsrcName) && pstatCborLen)
275             {
276                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
277                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
278                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
279                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
280             }
281             if (strcmp(OIC_JSON_DOXM_NAME, rsrcName) && doxmCborLen)
282             {
283                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
284                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
285                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
286                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
287             }
288             if (strcmp(OIC_JSON_AMACL_NAME, rsrcName) && amaclCborLen)
289             {
290                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME));
291                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Name.");
292                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, amaclCbor, amaclCborLen);
293                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Amacl Value.");
294             }
295             if (strcmp(OIC_JSON_SVC_NAME, rsrcName) && svcCborLen)
296             {
297                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_SVC_NAME, strlen(OIC_JSON_SVC_NAME));
298                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SVC Name.");
299                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, svcCbor, svcCborLen);
300                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SVC Value.");
301             }
302             if (strcmp(OIC_JSON_CRED_NAME, rsrcName) && credCborLen)
303             {
304                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
305                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Name.");
306                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, credCbor, credCborLen);
307                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Value.");
308             }
309             if (strcmp(OIC_JSON_PCONF_NAME, rsrcName) && pconfCborLen)
310             {
311                 cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PCONF_NAME, strlen(OIC_JSON_PCONF_NAME));
312                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Name.");
313                 cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pconfCbor, pconfCborLen);
314                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
315             }
316
317             cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
318             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
319             outSize = encoder.ptr - outPayload;
320         }
321     }
322     else if (psPayload && psSize)
323     {
324         size_t size = psSize + 255;
325         // This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
326
327         outPayload = (uint8_t *) OICCalloc(1, size);
328         VERIFY_NON_NULL(TAG, outPayload, ERROR);
329         CborEncoder encoder;  // will be initialized in |cbor_parser_init|
330         cbor_encoder_init(&encoder, outPayload, size, 0);
331         CborEncoder secRsrc;  // will be initialized in |cbor_encoder_create_map|
332         cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
333         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PS Map.");
334
335         cborEncoderResult |= cbor_encode_text_string(&secRsrc, rsrcName, strlen(rsrcName));
336         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value Tag");
337         cborEncoderResult |= cbor_encode_byte_string(&secRsrc, psPayload, psSize);
338         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Value.");
339
340         cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
341         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
342         outSize = encoder.ptr - outPayload;
343     }
344
345     if (outPayload && outSize)
346     {
347         OIC_LOG_V(DEBUG, TAG, "Writting in the file: %zu", outSize);
348         OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
349         if (ps)
350         {
351             FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "wb");
352             if (fp)
353             {
354                 size_t numberItems = ps->write(outPayload, 1, outSize, fp);
355                 if (outSize == numberItems)
356                 {
357                     OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", outSize);
358                     ret = OC_STACK_OK;
359                 }
360                 else
361                 {
362                     OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
363                 }
364                 ps->close(fp);
365             }
366             else
367             {
368                 OIC_LOG(ERROR, TAG, "File open failed.");
369             }
370         }
371     }
372
373     OIC_LOG(DEBUG, TAG, "UpdateSecureResourceInPS OUT");
374
375 exit:
376     OICFree(dbData);
377     OICFree(outPayload);
378     OICFree(aclCbor);
379     OICFree(pstatCbor);
380     OICFree(doxmCbor);
381     OICFree(amaclCbor);
382     OICFree(svcCbor);
383     OICFree(credCbor);
384     OICFree(pconfCbor);
385     return ret;
386 }