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);
255 // return everything in case rsrcName is NULL
265 OIC_LOG (ERROR, TAG, "Unable to open SVR database to read!! ");
276 OCStackResult UpdateSecureResourceInPS(const char* rsrcName, const uint8_t* psPayload, size_t psSize)
279 * This function stores cbor payload of each resource by appending resource name.
281 if (!rsrcName || !*psPayload)
283 return OC_STACK_INVALID_PARAM;
285 OCStackResult ret = OC_STACK_ERROR;
288 uint8_t *dbData = NULL;
289 uint8_t *outPayload = NULL;
292 ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
293 if (dbData && dbSize != 0)
295 uint8_t size = dbSize + psSize;
297 outPayload = (uint8_t *)OICCalloc(1, size);
298 VERIFY_NON_NULL(TAG, outPayload, ERROR);
300 CborEncoder encoder = { { .ptr = NULL }, .end = NULL, .added = 0, .flags = 0};
301 cbor_encoder_init(&encoder, outPayload, size, 0);
303 CborEncoder map = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0};
304 CborError cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
305 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating PS Interface Map.");
308 CborValue cbor = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
309 CborParser parser = { .end = NULL, .flags = 0 };
310 cbor_parser_init(dbData, size, 0, &parser, &cbor);
312 CborValue cborValue = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
313 CborError cborFindResult = CborNoError;
315 if (cbor_value_is_container(&cbor))
317 cborFindResult = cbor_value_enter_container(&cbor, &cborValue);
318 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering PS Interface Map.");
321 while (cbor_value_is_valid(&cborValue))
325 cborFindResult = cbor_value_dup_text_string(&cborValue, &name, &len, NULL);
326 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Duplicating Value.");
327 cborFindResult = cbor_value_advance(&cborValue);
328 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value.");
330 cborEncoderResult = cbor_encode_text_string(&map, name, strlen(name));
331 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Copying Text Str Value.");
333 if (strcmp(name, rsrcName) == 0)
335 cborEncoderResult = cbor_encode_byte_string(&map, psPayload, psSize);
336 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Encoding Byte String.");
341 uint8_t *byteString = NULL;
343 cborFindResult = cbor_value_dup_byte_string(&cborValue, &byteString, &byteLen, NULL);
344 VERIFY_SUCCESS(TAG, cborFindResult == CborNoError, ERROR);
347 cborEncoderResult = cbor_encode_byte_string(&map, byteString, byteLen);
348 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding value.");
353 cbor_value_advance(&cborValue);
356 // This is an exception when the value is not stored in the database.
359 cborEncoderResult = cbor_encode_text_string(&map, rsrcName, strlen(rsrcName));
360 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding value.");
361 cborEncoderResult = cbor_encode_byte_string(&map, psPayload, psSize);
362 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed entering byte string.");
365 cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
366 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed closing container.");
368 cborSize = encoder.ptr - outPayload;
372 OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
375 FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "w+");
378 size_t numberItems = ps->write(outPayload, 1, cborSize, fp);
379 if (cborSize == numberItems)
381 OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", cborSize);
386 OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
392 OIC_LOG(ERROR, TAG, "File open failed.");