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