You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/design-documents/features/storage/SecureStore/SecureStore_design.md
+19-19Lines changed: 19 additions & 19 deletions
Original file line number
Diff line number
Diff line change
@@ -47,10 +47,11 @@ SecureStore is a storage class, derived from KVStore. It adds security features
47
47
As such, it offers all KVStore APIs, with additional security options (which can be selected using the creation flags at set). These include:
48
48
49
49
- Encryption: Data is encrypted using the AES-CTR encryption method, with a randomly generated 8-byte IV. Key is derived from [Device Key](../../../../../../mbed-os/features/device_key/README.md), using the NIST SP 800-108 KDF in counter mode spec, where salt is the key trimmed to 32 bytes, with "ENC" as prefix. Flag here is called "require confidentiality flag".
50
-
- Authentication: A 16-byte CMAC is calculated on all stored data (including metadata) and stored at the end of the record. When reading the record, calculated CMAC is compared with the stored one. In the case of encryption, CMAC is calculated on the encrypted data. The key used for generating the CMAC is derived from [Device Key](../../../../../../mbed-os/features/device_key/README.md), where salt is the key trimmed to 32 bytes, with "AUTH" as prefix. Flag here is called "Require integrity flag".
51
50
- Rollback protection: (Requires authentication) CMAC is stored in a designated rollback protected storage (also of KVStore type) and compared to when reading the data under the same KVStore key. A missing or different key in the rollback protected storage results in an error. The flag here is called "Require replay protection flag".
52
51
- Write once: Key can only be stored once and can't be removed. The flag here is called "Write once flag".
53
52
53
+
SecureStore maintains data integrity using a record CMAC. This 16-byte CMAC is calculated on all stored data (including key & metadata) and stored at the end of the record. When reading the record, SecureStore compares the calculated CMAC with the stored one. In the case of encryption, CMAC is calculated on the encrypted data. The key used for generating the CMAC is derived from [Device Key](../../../../../../mbed-os/features/device_key/README.md), where salt is the key trimmed to 32 bytes, with "AUTH" as prefix.
54
+
54
55

55
56
56
57
### Data layout
@@ -73,7 +74,8 @@ Fields are:
73
74
74
75
Because the code can't construct a single buffer to store all data (including metadata and possibly encrypted data) in one shot, setting the data occurs in chunks, using the incremental set APIs. Get uses the offset argument to extract metadata, data and CMAC separately.
75
76
76
-
Rollback protection (RBP) keys are stored in the designated rollback protection storage, which is also of KVStore type. RBP keys are the same as the SecureStore keys.
77
+
Rollback protection (RBP) keys are stored in the designated rollback protection storage, which is also of KVStore type. RBP keys are the same as the SecureStore keys.
78
+
This RBP storage is also used for storing the CMAC in write once case, as otherwise an attacker can delete this key from the underlying storage and modify this flag.
77
79
78
80
# Detailed design
79
81
@@ -227,14 +229,13 @@ Pseudo code:
227
229
- Take `_mutex`.
228
230
- Call `_underlying_kv``get` API with `metadata` size into a `metadata` local structure.
229
231
- If failure:
230
-
- If rollback protection flag set:
232
+
- If rollback protection or write once flag set:
231
233
- Call `_rbp_kv` `get` API on a local `rbp_cmac` variable, key is `key`, size 16.
232
234
- If no error, return "RBP authentication" error.
233
235
- Return "Key not found error".
234
-
- If authentication flag set:
235
-
- Derive a key from device key and `key`.
236
-
- Allocate and initialize `auth_handle` CMAC calculation local handle with derived key.
237
-
- Using `auth_handle` handle, calculate CMAC on `key` and `metadata`.
236
+
- Derive a key from device key and `key`.
237
+
- Allocate and initialize `auth_handle` CMAC calculation local handle with derived key.
238
+
- Using `auth_handle` handle, calculate CMAC on `key` and `metadata`.
238
239
- If encrypt flag set:
239
240
- Derive a key from device key and `key`.
240
241
- Allocate and initialize a local `enc_handle` AES-CTR local handle with derived key and `iv` field.
@@ -247,13 +248,13 @@ Pseudo code:
247
248
- Else:
248
249
- Set `dest_buf` to `_scratch_buf` and `chunk_size` to `actual_size`.
249
250
- Call `_underlying_kv` `get` API with `dest_buf` and `chunk_size`.
250
-
- If authentication flag set, calculate CMAC on `dest_buf`, using `_auth_handle` handle.
251
+
- Calculate CMAC on `dest_buf`, using `_auth_handle` handle.
251
252
- If encrypt flag set, decrypt `dest_buf` (in place) using `_enc_handle` handle.
252
253
- Decrement `data_size` by `chunk_size`.
253
254
- Call `_underlying_kv``get` API with on a local `read_cmac` variable, size 16.
254
255
- Generate CMAC on local `cmac` variable .
255
256
- Using `mbedtls_ssl_safer_memcmp` function, compare `read_cmac` with `cmac`. Return "data corrupt error" if no match.
256
-
- If rollback protection flag set:
257
+
- If rollback protection or write once flags set:
257
258
- Call `_rbp_kv` `get` API on a local `rbp_cmac` variable, key is `key`, size 16.
258
259
- If `rbp_cmac` doesn't match `cmac`, clear `buffer` and return "RBP authentication" error.
259
260
- Deinitialize and free `auth_handle` and `enc_handle`.
@@ -312,10 +313,9 @@ Pseudo code:
312
313
- Using TLS entropy function on `_entropy` handle, randomly generate `iv` field.
313
314
- Allocate and initialize `enc_handle` AES-CTR handle field with derived key and `iv` field.
314
315
- Fill all available fields in `metadata`.
315
-
- If authentication flag set:
316
-
- Derive a key from device key and `key` as salt (trimmed to 32 bytes with "AUTH" as prefix).
317
-
- Allocate and initialize `auth_handle` CMAC calculation handle field with derived key.
318
-
- Using `auth_handle` handle, calculate CMAC on `key` and `metadata`.
316
+
- Derive a key from device key and `key` as salt (trimmed to 32 bytes with "AUTH" as prefix).
317
+
- Allocate and initialize `auth_handle` CMAC calculation handle field with derived key.
318
+
- Using `auth_handle` handle, calculate CMAC on `key` and `metadata`.
319
319
- Call `_underlying_kv``set_start` API.
320
320
- Call `_underlying_kv``set_add_data` API with `metadata` field.
321
321
- Return OK.
@@ -332,10 +332,10 @@ Pseudo code:
332
332
- If flags include encryption:
333
333
- Iterate over `value_data` field in chunks of `_scratch_buf` size.
334
334
- Using `enc_handle` handle field, encrypt chunk into `_scratch_buf`.
335
-
- If authentication flag set, using `auth_handle` handle field, update CMAC of `_scratch_buf`.
335
+
- Using `auth_handle` handle field, update CMAC of `_scratch_buf`.
336
336
- Call `_underlying_kv` `set_add_data` API with `_scratch_buf`.
337
337
- Else:
338
-
- If authentication flag set, using `auth_handle` handle field, update CMAC of `value_data`.
338
+
- Using `auth_handle` handle field, update CMAC of `value_data`.
339
339
- Call `_underlying_kv` `set_add_data` API with `value_data`.
340
340
- Update `offset` field in handle.
341
341
- Return OK.
@@ -352,7 +352,7 @@ Pseudo code:
352
352
- If authentication flag set, using `auth_handle` handle field, generate `cmac`.
353
353
- Call `_underlying_kv``set_add_data` API with `cmac`.
354
354
- Call `_underlying_kv``set_finalize`.
355
-
- If rollback protect flag set, call `_rbp_kv``set` API with `key` as key and `cmac` as data.
355
+
- If rollback protect or write once flags set, call `_rbp_kv``set` API with `key` as key and `cmac` as data.
356
356
- Deinitialize and free `auth_handle` and `enc_handle`.
357
357
- Free `handle`.
358
358
- Release `_mutex`.
@@ -426,10 +426,10 @@ res = secure_store.init();
426
426
427
427
const char *val1 = "Value of key 1";
428
428
const char *val2 = "Updated value of key 1";
429
-
// Add "Key1" with encryption and authentication flags
430
-
res = secure_store.set("Key1", val1, sizeof(val1), KVSTore::REQUIRE_CONFIDENTIALITY_FLAG | KVSTore::REQUIRE_INTEGRITY_FLAG);
429
+
// Add "Key1" with encryption flag
430
+
res = secure_store.set("Key1", val1, sizeof(val1), KVSTore::REQUIRE_CONFIDENTIALITY_FLAG);
431
431
// Update value of "Key1" (flags must be the same per key)
432
-
res = secure_store.set("Key1", val2, sizeof(val2), KVSTore::REQUIRE_CONFIDENTIALITY_FLAG | KVSTore::REQUIRE_INTEGRITY_FLAG);
432
+
res = secure_store.set("Key1", val2, sizeof(val2), KVSTore::REQUIRE_CONFIDENTIALITY_FLAG);
0 commit comments