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