1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #define __STDC_LIMIT_MACROS
28 #include "oic_malloc.h"
29 #include "ocpayload.h"
30 #include "ocpayloadcbor.h"
31 #include "payload_logging.h"
33 #include "cainterface.h"
34 #include "secureresourcemanager.h"
35 #include "resourcemanager.h"
36 #include "srmresourcestrings.h"
37 #include "srmutility.h"
41 //SVR database buffer block size
42 const size_t DB_FILE_SIZE_BLOCK = 1023;
45 * Gets the Secure Virtual Database size.
47 * @param ps pointer of OCPersistentStorage for the SVR name ("acl", "cred", "pstat" etc).
49 * @return total size of the SVR database.
51 static size_t GetSVRDatabaseSize(const OCPersistentStorage* ps)
59 char buffer[DB_FILE_SIZE_BLOCK];
60 FILE* fp = ps->open(SVR_DB_DAT_FILE_NAME, "r");
65 bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
67 } while (bytesRead > 0);
73 char* GetSVRDatabase()
75 char * jsonStr = NULL;
77 OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
78 int size = GetSVRDatabaseSize(ps);
81 OIC_LOG (ERROR, TAG, "FindSVRDatabaseSize failed");
87 // Open default SRM database file. An app could change the path for its server.
88 fp = ps->open(SVR_DB_FILE_NAME, "r");
91 jsonStr = (char*)OICMalloc(size + 1);
92 VERIFY_NON_NULL(TAG, jsonStr, FATAL);
93 size_t bytesRead = ps->read(jsonStr, 1, size, fp);
94 jsonStr[bytesRead] = '\0';
96 OIC_LOG_V(DEBUG, TAG, "Read %zu bytes from SVR database file", bytesRead);
102 OIC_LOG (ERROR, TAG, "Unable to open SVR database file!!");
114 OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
116 OCStackResult ret = OC_STACK_ERROR;
117 cJSON *jsonSVRDb = NULL;
118 OCPersistentStorage* ps = NULL;
120 // Read SVR database from PS
121 char* jsonSVRDbStr = GetSVRDatabase();
122 VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
124 // Use cJSON_Parse to parse the existing SVR database
125 jsonSVRDb = cJSON_Parse(jsonSVRDbStr);
126 VERIFY_NON_NULL(TAG,jsonSVRDb, ERROR);
128 OICFree(jsonSVRDbStr);
131 //If Cred resource gets updated with empty list then delete the Cred
132 //object from database.
133 if(NULL == jsonObj && (0 == strcmp(rsrcName, OIC_JSON_CRED_NAME)))
135 cJSON_DeleteItemFromObject(jsonSVRDb, rsrcName);
137 else if (jsonObj->child )
139 // Create a duplicate of the JSON object which was passed.
140 cJSON* jsonDuplicateObj = cJSON_Duplicate(jsonObj, 1);
141 VERIFY_NON_NULL(TAG,jsonDuplicateObj, ERROR);
143 cJSON* jsonObj = cJSON_GetObjectItem(jsonSVRDb, rsrcName);
146 ACL, PStat & Doxm resources at least have default entries in the database but
147 Cred resource may have no entries. The first cred resource entry (for provisioning tool)
148 is created when the device is owned by provisioning tool and it's ownerpsk is generated.*/
149 if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0 ||
150 strcmp(rsrcName, OIC_JSON_CRL_NAME) == 0 ||
151 strcmp(rsrcName, OIC_JSON_PCONF_NAME) == 0 ||
152 strcmp(rsrcName, OIC_JSON_DPAIRING_NAME) == 0) && (!jsonObj))
154 // Add the fist cred object in existing SVR database json
155 cJSON_AddItemToObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
159 VERIFY_NON_NULL(TAG,jsonObj, ERROR);
161 // Replace the modified json object in existing SVR database json
162 cJSON_ReplaceItemInObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
166 // Generate string representation of updated SVR database json object
167 jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
168 VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
170 // Update the persistent storage with new SVR database
171 ps = SRMGetPersistentStorageHandler();
174 FILE* fp = ps->open(SVR_DB_FILE_NAME, "w");
177 size_t bytesWritten = ps->write(jsonSVRDbStr, 1, strlen(jsonSVRDbStr), fp);
178 if (bytesWritten == strlen(jsonSVRDbStr))
182 OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", bytesWritten);
188 OIC_LOG (ERROR, TAG, "Unable to open SVR database file!! ");
193 OICFree(jsonSVRDbStr);
194 cJSON_Delete(jsonSVRDb);
199 OCStackResult GetSecureVirtualDatabaseFromPS(const char *rsrcName, uint8_t **data, size_t *size)
203 return OC_STACK_INVALID_PARAM;
205 OCStackResult ret = OC_STACK_ERROR;
211 OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
212 VERIFY_NON_NULL(TAG, ps, ERROR);
214 fileSize = GetSVRDatabaseSize(ps);
217 OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
218 uint8_t *fsData = (uint8_t *)OICCalloc(1, fileSize);
219 VERIFY_NON_NULL(TAG, fsData, ERROR);
221 FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "r");
222 VERIFY_NON_NULL(TAG, fp, ERROR);
223 size_t itemsRead = ps->read(fsData, 1, fileSize, fp);
224 if (itemsRead == fileSize)
226 VERIFY_NON_NULL(TAG, fsData, ERROR);
227 if (rsrcName != NULL)
229 CborParser parser = { .end = NULL, .flags = 0 };
230 CborValue cbor = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
231 cbor_parser_init(fsData, fileSize, 0, &parser, &cbor);
232 CborValue cborValue = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
233 CborError cborFindResult = cbor_value_enter_container(&cbor, &cborValue);
235 while (cbor_value_is_valid(&cborValue))
239 cborFindResult = cbor_value_dup_text_string(&cborValue, &name, &len, NULL);
240 VERIFY_SUCCESS(TAG, cborFindResult == CborNoError, ERROR);
241 cborFindResult = cbor_value_advance(&cborValue);
242 VERIFY_SUCCESS(TAG, cborFindResult == CborNoError, ERROR);
243 if (strcmp(name, rsrcName) == 0)
245 cborFindResult = cbor_value_dup_byte_string(&cborValue, data, size, NULL);
246 VERIFY_SUCCESS(TAG, cborFindResult == CborNoError, ERROR);
253 cborFindResult = cbor_value_advance(&cborValue);
254 VERIFY_SUCCESS(TAG, cborFindResult == CborNoError, ERROR);
257 // return everything in case rsrcName is NULL
267 OIC_LOG(ERROR, TAG, "Unable to open SVR database to read!! ");
278 OCStackResult UpdateSecureResourceInPS(const char* rsrcName, const uint8_t* psPayload, size_t psSize)
281 * This function stores cbor payload of each resource by appending resource name.
283 if (!rsrcName || !*psPayload)
285 return OC_STACK_INVALID_PARAM;
287 OCStackResult ret = OC_STACK_ERROR;
290 uint8_t *dbData = NULL;
291 uint8_t *outPayload = NULL;
294 ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
295 if (dbData && dbSize != 0)
297 uint8_t size = dbSize + psSize;
299 outPayload = (uint8_t *)OICCalloc(1, size);
300 VERIFY_NON_NULL(TAG, outPayload, ERROR);
302 CborEncoder encoder = { { .ptr = NULL }, .end = NULL, .added = 0, .flags = 0};
303 cbor_encoder_init(&encoder, outPayload, size, 0);
305 CborEncoder map = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0};
306 CborError cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
307 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating PS Interface Map.");
310 CborValue cbor = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
311 CborParser parser = { .end = NULL, .flags = 0 };
312 cbor_parser_init(dbData, size, 0, &parser, &cbor);
314 CborValue cborValue = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
315 CborError cborFindResult = CborNoError;
317 if (cbor_value_is_container(&cbor))
319 cborFindResult = cbor_value_enter_container(&cbor, &cborValue);
320 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering PS Interface Map.");
323 while (cbor_value_is_valid(&cborValue))
327 cborFindResult = cbor_value_dup_text_string(&cborValue, &name, &len, NULL);
328 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Duplicating Value.");
329 cborFindResult = cbor_value_advance(&cborValue);
330 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value.");
332 cborEncoderResult = cbor_encode_text_string(&map, name, strlen(name));
333 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Copying Text Str Value.");
335 if (strcmp(name, rsrcName) == 0)
337 cborEncoderResult = cbor_encode_byte_string(&map, psPayload, psSize);
338 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Encoding Byte String.");
343 uint8_t *byteString = NULL;
345 cborFindResult = cbor_value_dup_byte_string(&cborValue, &byteString, &byteLen, NULL);
346 VERIFY_SUCCESS(TAG, cborFindResult == CborNoError, ERROR);
349 cborEncoderResult = cbor_encode_byte_string(&map, byteString, byteLen);
350 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding value.");
355 cbor_value_advance(&cborValue);
358 // This is an exception when the value is not stored in the database.
361 cborEncoderResult = cbor_encode_text_string(&map, rsrcName, strlen(rsrcName));
362 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding value.");
363 cborEncoderResult = cbor_encode_byte_string(&map, psPayload, psSize);
364 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed entering byte string.");
367 cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
368 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing container.");
370 cborSize = encoder.ptr - outPayload;
374 OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
377 FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "w+");
380 size_t numberItems = ps->write(outPayload, 1, cborSize, fp);
381 if (cborSize == numberItems)
383 OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", cborSize);
388 OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
394 OIC_LOG(ERROR, TAG, "File open failed.");