Mauro Carvalho Chehab | 688f118 | 2020-02-17 17:12:27 +0100 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 3 | :orphan: |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 4 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 5 | .. UBIFS Authentication |
| 6 | .. sigma star gmbh |
| 7 | .. 2018 |
| 8 | |
| 9 | Introduction |
| 10 | ============ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 11 | |
| 12 | UBIFS utilizes the fscrypt framework to provide confidentiality for file |
| 13 | contents and file names. This prevents attacks where an attacker is able to |
| 14 | read contents of the filesystem on a single point in time. A classic example |
| 15 | is a lost smartphone where the attacker is unable to read personal data stored |
| 16 | on the device without the filesystem decryption key. |
| 17 | |
| 18 | At the current state, UBIFS encryption however does not prevent attacks where |
| 19 | the attacker is able to modify the filesystem contents and the user uses the |
| 20 | device afterwards. In such a scenario an attacker can modify filesystem |
| 21 | contents arbitrarily without the user noticing. One example is to modify a |
| 22 | binary to perform a malicious action when executed [DMC-CBC-ATTACK]. Since |
| 23 | most of the filesystem metadata of UBIFS is stored in plain, this makes it |
| 24 | fairly easy to swap files and replace their contents. |
| 25 | |
| 26 | Other full disk encryption systems like dm-crypt cover all filesystem metadata, |
| 27 | which makes such kinds of attacks more complicated, but not impossible. |
| 28 | Especially, if the attacker is given access to the device multiple points in |
| 29 | time. For dm-crypt and other filesystems that build upon the Linux block IO |
| 30 | layer, the dm-integrity or dm-verity subsystems [DM-INTEGRITY, DM-VERITY] |
| 31 | can be used to get full data authentication at the block layer. |
| 32 | These can also be combined with dm-crypt [CRYPTSETUP2]. |
| 33 | |
| 34 | This document describes an approach to get file contents _and_ full metadata |
| 35 | authentication for UBIFS. Since UBIFS uses fscrypt for file contents and file |
| 36 | name encryption, the authentication system could be tied into fscrypt such that |
| 37 | existing features like key derivation can be utilized. It should however also |
| 38 | be possible to use UBIFS authentication without using encryption. |
| 39 | |
| 40 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 41 | MTD, UBI & UBIFS |
| 42 | ---------------- |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 43 | |
| 44 | On Linux, the MTD (Memory Technology Devices) subsystem provides a uniform |
| 45 | interface to access raw flash devices. One of the more prominent subsystems that |
| 46 | work on top of MTD is UBI (Unsorted Block Images). It provides volume management |
| 47 | for flash devices and is thus somewhat similar to LVM for block devices. In |
| 48 | addition, it deals with flash-specific wear-leveling and transparent I/O error |
| 49 | handling. UBI offers logical erase blocks (LEBs) to the layers on top of it |
| 50 | and maps them transparently to physical erase blocks (PEBs) on the flash. |
| 51 | |
| 52 | UBIFS is a filesystem for raw flash which operates on top of UBI. Thus, wear |
| 53 | leveling and some flash specifics are left to UBI, while UBIFS focuses on |
| 54 | scalability, performance and recoverability. |
| 55 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 56 | :: |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 57 | |
| 58 | +------------+ +*******+ +-----------+ +-----+ |
| 59 | | | * UBIFS * | UBI-BLOCK | | ... | |
| 60 | | JFFS/JFFS2 | +*******+ +-----------+ +-----+ |
| 61 | | | +-----------------------------+ +-----------+ +-----+ |
| 62 | | | | UBI | | MTD-BLOCK | | ... | |
| 63 | +------------+ +-----------------------------+ +-----------+ +-----+ |
| 64 | +------------------------------------------------------------------+ |
| 65 | | MEMORY TECHNOLOGY DEVICES (MTD) | |
| 66 | +------------------------------------------------------------------+ |
| 67 | +-----------------------------+ +--------------------------+ +-----+ |
| 68 | | NAND DRIVERS | | NOR DRIVERS | | ... | |
| 69 | +-----------------------------+ +--------------------------+ +-----+ |
| 70 | |
| 71 | Figure 1: Linux kernel subsystems for dealing with raw flash |
| 72 | |
| 73 | |
| 74 | |
| 75 | Internally, UBIFS maintains multiple data structures which are persisted on |
| 76 | the flash: |
| 77 | |
| 78 | - *Index*: an on-flash B+ tree where the leaf nodes contain filesystem data |
| 79 | - *Journal*: an additional data structure to collect FS changes before updating |
| 80 | the on-flash index and reduce flash wear. |
| 81 | - *Tree Node Cache (TNC)*: an in-memory B+ tree that reflects the current FS |
| 82 | state to avoid frequent flash reads. It is basically the in-memory |
| 83 | representation of the index, but contains additional attributes. |
| 84 | - *LEB property tree (LPT)*: an on-flash B+ tree for free space accounting per |
| 85 | UBI LEB. |
| 86 | |
| 87 | In the remainder of this section we will cover the on-flash UBIFS data |
| 88 | structures in more detail. The TNC is of less importance here since it is never |
| 89 | persisted onto the flash directly. More details on UBIFS can also be found in |
| 90 | [UBIFS-WP]. |
| 91 | |
| 92 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 93 | UBIFS Index & Tree Node Cache |
| 94 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 95 | |
| 96 | Basic on-flash UBIFS entities are called *nodes*. UBIFS knows different types |
Mauro Carvalho Chehab | 688f118 | 2020-02-17 17:12:27 +0100 | [diff] [blame] | 97 | of nodes. Eg. data nodes (``struct ubifs_data_node``) which store chunks of file |
| 98 | contents or inode nodes (``struct ubifs_ino_node``) which represent VFS inodes. |
| 99 | Almost all types of nodes share a common header (``ubifs_ch``) containing basic |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 100 | information like node type, node length, a sequence number, etc. (see |
Mauro Carvalho Chehab | 688f118 | 2020-02-17 17:12:27 +0100 | [diff] [blame] | 101 | ``fs/ubifs/ubifs-media.h`` in kernel source). Exceptions are entries of the LPT |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 102 | and some less important node types like padding nodes which are used to pad |
| 103 | unusable content at the end of LEBs. |
| 104 | |
| 105 | To avoid re-writing the whole B+ tree on every single change, it is implemented |
| 106 | as *wandering tree*, where only the changed nodes are re-written and previous |
| 107 | versions of them are obsoleted without erasing them right away. As a result, |
| 108 | the index is not stored in a single place on the flash, but *wanders* around |
| 109 | and there are obsolete parts on the flash as long as the LEB containing them is |
| 110 | not reused by UBIFS. To find the most recent version of the index, UBIFS stores |
| 111 | a special node called *master node* into UBI LEB 1 which always points to the |
| 112 | most recent root node of the UBIFS index. For recoverability, the master node |
| 113 | is additionally duplicated to LEB 2. Mounting UBIFS is thus a simple read of |
| 114 | LEB 1 and 2 to get the current master node and from there get the location of |
| 115 | the most recent on-flash index. |
| 116 | |
| 117 | The TNC is the in-memory representation of the on-flash index. It contains some |
| 118 | additional runtime attributes per node which are not persisted. One of these is |
| 119 | a dirty-flag which marks nodes that have to be persisted the next time the |
| 120 | index is written onto the flash. The TNC acts as a write-back cache and all |
| 121 | modifications of the on-flash index are done through the TNC. Like other caches, |
| 122 | the TNC does not have to mirror the full index into memory, but reads parts of |
| 123 | it from flash whenever needed. A *commit* is the UBIFS operation of updating the |
| 124 | on-flash filesystem structures like the index. On every commit, the TNC nodes |
| 125 | marked as dirty are written to the flash to update the persisted index. |
| 126 | |
| 127 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 128 | Journal |
| 129 | ~~~~~~~ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 130 | |
| 131 | To avoid wearing out the flash, the index is only persisted (*commited*) when |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 132 | certain conditions are met (eg. ``fsync(2)``). The journal is used to record |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 133 | any changes (in form of inode nodes, data nodes etc.) between commits |
| 134 | of the index. During mount, the journal is read from the flash and replayed |
| 135 | onto the TNC (which will be created on-demand from the on-flash index). |
| 136 | |
| 137 | UBIFS reserves a bunch of LEBs just for the journal called *log area*. The |
| 138 | amount of log area LEBs is configured on filesystem creation (using |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 139 | ``mkfs.ubifs``) and stored in the superblock node. The log area contains only |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 140 | two types of nodes: *reference nodes* and *commit start nodes*. A commit start |
| 141 | node is written whenever an index commit is performed. Reference nodes are |
| 142 | written on every journal update. Each reference node points to the position of |
| 143 | other nodes (inode nodes, data nodes etc.) on the flash that are part of this |
| 144 | journal entry. These nodes are called *buds* and describe the actual filesystem |
| 145 | changes including their data. |
| 146 | |
| 147 | The log area is maintained as a ring. Whenever the journal is almost full, |
| 148 | a commit is initiated. This also writes a commit start node so that during |
| 149 | mount, UBIFS will seek for the most recent commit start node and just replay |
| 150 | every reference node after that. Every reference node before the commit start |
| 151 | node will be ignored as they are already part of the on-flash index. |
| 152 | |
| 153 | When writing a journal entry, UBIFS first ensures that enough space is |
| 154 | available to write the reference node and buds part of this entry. Then, the |
| 155 | reference node is written and afterwards the buds describing the file changes. |
| 156 | On replay, UBIFS will record every reference node and inspect the location of |
| 157 | the referenced LEBs to discover the buds. If these are corrupt or missing, |
| 158 | UBIFS will attempt to recover them by re-reading the LEB. This is however only |
| 159 | done for the last referenced LEB of the journal. Only this can become corrupt |
| 160 | because of a power cut. If the recovery fails, UBIFS will not mount. An error |
| 161 | for every other LEB will directly cause UBIFS to fail the mount operation. |
| 162 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 163 | :: |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 164 | |
| 165 | | ---- LOG AREA ---- | ---------- MAIN AREA ------------ | |
| 166 | |
| 167 | -----+------+-----+--------+---- ------+-----+-----+--------------- |
| 168 | \ | | | | / / | | | \ |
| 169 | / CS | REF | REF | | \ \ DENT | INO | INO | / |
| 170 | \ | | | | / / | | | \ |
| 171 | ----+------+-----+--------+--- -------+-----+-----+---------------- |
| 172 | | | ^ ^ |
| 173 | | | | | |
| 174 | +------------------------+ | |
| 175 | | | |
| 176 | +-------------------------------+ |
| 177 | |
| 178 | |
| 179 | Figure 2: UBIFS flash layout of log area with commit start nodes |
| 180 | (CS) and reference nodes (REF) pointing to main area |
| 181 | containing their buds |
| 182 | |
| 183 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 184 | LEB Property Tree/Table |
| 185 | ~~~~~~~~~~~~~~~~~~~~~~~ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 186 | |
| 187 | The LEB property tree is used to store per-LEB information. This includes the |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 188 | LEB type and amount of free and *dirty* (old, obsolete content) space [1]_ on |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 189 | the LEB. The type is important, because UBIFS never mixes index nodes with data |
| 190 | nodes on a single LEB and thus each LEB has a specific purpose. This again is |
| 191 | useful for free space calculations. See [UBIFS-WP] for more details. |
| 192 | |
| 193 | The LEB property tree again is a B+ tree, but it is much smaller than the |
| 194 | index. Due to its smaller size it is always written as one chunk on every |
| 195 | commit. Thus, saving the LPT is an atomic operation. |
| 196 | |
| 197 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 198 | .. [1] Since LEBs can only be appended and never overwritten, there is a |
| 199 | difference between free space ie. the remaining space left on the LEB to be |
| 200 | written to without erasing it and previously written content that is obsolete |
| 201 | but can't be overwritten without erasing the full LEB. |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 202 | |
| 203 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 204 | UBIFS Authentication |
| 205 | ==================== |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 206 | |
| 207 | This chapter introduces UBIFS authentication which enables UBIFS to verify |
| 208 | the authenticity and integrity of metadata and file contents stored on flash. |
| 209 | |
| 210 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 211 | Threat Model |
| 212 | ------------ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 213 | |
| 214 | UBIFS authentication enables detection of offline data modification. While it |
| 215 | does not prevent it, it enables (trusted) code to check the integrity and |
| 216 | authenticity of on-flash file contents and filesystem metadata. This covers |
| 217 | attacks where file contents are swapped. |
| 218 | |
| 219 | UBIFS authentication will not protect against rollback of full flash contents. |
| 220 | Ie. an attacker can still dump the flash and restore it at a later time without |
| 221 | detection. It will also not protect against partial rollback of individual |
| 222 | index commits. That means that an attacker is able to partially undo changes. |
| 223 | This is possible because UBIFS does not immediately overwrites obsolete |
| 224 | versions of the index tree or the journal, but instead marks them as obsolete |
| 225 | and garbage collection erases them at a later time. An attacker can use this by |
| 226 | erasing parts of the current tree and restoring old versions that are still on |
| 227 | the flash and have not yet been erased. This is possible, because every commit |
| 228 | will always write a new version of the index root node and the master node |
| 229 | without overwriting the previous version. This is further helped by the |
| 230 | wear-leveling operations of UBI which copies contents from one physical |
| 231 | eraseblock to another and does not atomically erase the first eraseblock. |
| 232 | |
| 233 | UBIFS authentication does not cover attacks where an attacker is able to |
| 234 | execute code on the device after the authentication key was provided. |
| 235 | Additional measures like secure boot and trusted boot have to be taken to |
| 236 | ensure that only trusted code is executed on a device. |
| 237 | |
| 238 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 239 | Authentication |
| 240 | -------------- |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 241 | |
| 242 | To be able to fully trust data read from flash, all UBIFS data structures |
| 243 | stored on flash are authenticated. That is: |
| 244 | |
| 245 | - The index which includes file contents, file metadata like extended |
| 246 | attributes, file length etc. |
| 247 | - The journal which also contains file contents and metadata by recording changes |
| 248 | to the filesystem |
| 249 | - The LPT which stores UBI LEB metadata which UBIFS uses for free space accounting |
| 250 | |
| 251 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 252 | Index Authentication |
| 253 | ~~~~~~~~~~~~~~~~~~~~ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 254 | |
| 255 | Through UBIFS' concept of a wandering tree, it already takes care of only |
| 256 | updating and persisting changed parts from leaf node up to the root node |
| 257 | of the full B+ tree. This enables us to augment the index nodes of the tree |
| 258 | with a hash over each node's child nodes. As a result, the index basically also |
| 259 | a Merkle tree. Since the leaf nodes of the index contain the actual filesystem |
| 260 | data, the hashes of their parent index nodes thus cover all the file contents |
| 261 | and file metadata. When a file changes, the UBIFS index is updated accordingly |
| 262 | from the leaf nodes up to the root node including the master node. This process |
| 263 | can be hooked to recompute the hash only for each changed node at the same time. |
| 264 | Whenever a file is read, UBIFS can verify the hashes from each leaf node up to |
| 265 | the root node to ensure the node's integrity. |
| 266 | |
| 267 | To ensure the authenticity of the whole index, the UBIFS master node stores a |
| 268 | keyed hash (HMAC) over its own contents and a hash of the root node of the index |
| 269 | tree. As mentioned above, the master node is always written to the flash whenever |
| 270 | the index is persisted (ie. on index commit). |
| 271 | |
| 272 | Using this approach only UBIFS index nodes and the master node are changed to |
| 273 | include a hash. All other types of nodes will remain unchanged. This reduces |
| 274 | the storage overhead which is precious for users of UBIFS (ie. embedded |
| 275 | devices). |
| 276 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 277 | :: |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 278 | |
| 279 | +---------------+ |
| 280 | | Master Node | |
| 281 | | (hash) | |
| 282 | +---------------+ |
| 283 | | |
| 284 | v |
| 285 | +-------------------+ |
| 286 | | Index Node #1 | |
| 287 | | | |
| 288 | | branch0 branchn | |
| 289 | | (hash) (hash) | |
| 290 | +-------------------+ |
| 291 | | ... | (fanout: 8) |
| 292 | | | |
| 293 | +-------+ +------+ |
| 294 | | | |
| 295 | v v |
| 296 | +-------------------+ +-------------------+ |
| 297 | | Index Node #2 | | Index Node #3 | |
| 298 | | | | | |
| 299 | | branch0 branchn | | branch0 branchn | |
| 300 | | (hash) (hash) | | (hash) (hash) | |
| 301 | +-------------------+ +-------------------+ |
| 302 | | ... | ... | |
| 303 | v v v |
| 304 | +-----------+ +----------+ +-----------+ |
| 305 | | Data Node | | INO Node | | DENT Node | |
| 306 | +-----------+ +----------+ +-----------+ |
| 307 | |
| 308 | |
| 309 | Figure 3: Coverage areas of index node hash and master node HMAC |
| 310 | |
| 311 | |
| 312 | |
| 313 | The most important part for robustness and power-cut safety is to atomically |
| 314 | persist the hash and file contents. Here the existing UBIFS logic for how |
| 315 | changed nodes are persisted is already designed for this purpose such that |
| 316 | UBIFS can safely recover if a power-cut occurs while persisting. Adding |
| 317 | hashes to index nodes does not change this since each hash will be persisted |
| 318 | atomically together with its respective node. |
| 319 | |
| 320 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 321 | Journal Authentication |
| 322 | ~~~~~~~~~~~~~~~~~~~~~~ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 323 | |
| 324 | The journal is authenticated too. Since the journal is continuously written |
| 325 | it is necessary to also add authentication information frequently to the |
| 326 | journal so that in case of a powercut not too much data can't be authenticated. |
| 327 | This is done by creating a continuous hash beginning from the commit start node |
| 328 | over the previous reference nodes, the current reference node, and the bud |
| 329 | nodes. From time to time whenever it is suitable authentication nodes are added |
| 330 | between the bud nodes. This new node type contains a HMAC over the current state |
| 331 | of the hash chain. That way a journal can be authenticated up to the last |
| 332 | authentication node. The tail of the journal which may not have a authentication |
| 333 | node cannot be authenticated and is skipped during journal replay. |
| 334 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 335 | We get this picture for journal authentication:: |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 336 | |
| 337 | ,,,,,,,, |
| 338 | ,......,........................................... |
| 339 | ,. CS , hash1.----. hash2.----. |
| 340 | ,. | , . |hmac . |hmac |
| 341 | ,. v , . v . v |
| 342 | ,.REF#0,-> bud -> bud -> bud.-> auth -> bud -> bud.-> auth ... |
| 343 | ,..|...,........................................... |
| 344 | , | , |
| 345 | , | ,,,,,,,,,,,,,,, |
| 346 | . | hash3,----. |
| 347 | , | , |hmac |
| 348 | , v , v |
| 349 | , REF#1 -> bud -> bud,-> auth ... |
| 350 | ,,,|,,,,,,,,,,,,,,,,,, |
| 351 | v |
| 352 | REF#2 -> ... |
| 353 | | |
| 354 | V |
| 355 | ... |
| 356 | |
| 357 | Since the hash also includes the reference nodes an attacker cannot reorder or |
| 358 | skip any journal heads for replay. An attacker can only remove bud nodes or |
| 359 | reference nodes from the end of the journal, effectively rewinding the |
| 360 | filesystem at maximum back to the last commit. |
| 361 | |
| 362 | The location of the log area is stored in the master node. Since the master |
| 363 | node is authenticated with a HMAC as described above, it is not possible to |
| 364 | tamper with that without detection. The size of the log area is specified when |
| 365 | the filesystem is created using `mkfs.ubifs` and stored in the superblock node. |
| 366 | To avoid tampering with this and other values stored there, a HMAC is added to |
| 367 | the superblock struct. The superblock node is stored in LEB 0 and is only |
| 368 | modified on feature flag or similar changes, but never on file changes. |
| 369 | |
| 370 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 371 | LPT Authentication |
| 372 | ~~~~~~~~~~~~~~~~~~ |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 373 | |
| 374 | The location of the LPT root node on the flash is stored in the UBIFS master |
| 375 | node. Since the LPT is written and read atomically on every commit, there is |
| 376 | no need to authenticate individual nodes of the tree. It suffices to |
| 377 | protect the integrity of the full LPT by a simple hash stored in the master |
| 378 | node. Since the master node itself is authenticated, the LPTs authenticity can |
| 379 | be verified by verifying the authenticity of the master node and comparing the |
| 380 | LTP hash stored there with the hash computed from the read on-flash LPT. |
| 381 | |
| 382 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 383 | Key Management |
| 384 | -------------- |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 385 | |
| 386 | For simplicity, UBIFS authentication uses a single key to compute the HMACs |
| 387 | of superblock, master, commit start and reference nodes. This key has to be |
| 388 | available on creation of the filesystem (`mkfs.ubifs`) to authenticate the |
| 389 | superblock node. Further, it has to be available on mount of the filesystem |
| 390 | to verify authenticated nodes and generate new HMACs for changes. |
| 391 | |
| 392 | UBIFS authentication is intended to operate side-by-side with UBIFS encryption |
| 393 | (fscrypt) to provide confidentiality and authenticity. Since UBIFS encryption |
| 394 | has a different approach of encryption policies per directory, there can be |
| 395 | multiple fscrypt master keys and there might be folders without encryption. |
| 396 | UBIFS authentication on the other hand has an all-or-nothing approach in the |
| 397 | sense that it either authenticates everything of the filesystem or nothing. |
| 398 | Because of this and because UBIFS authentication should also be usable without |
| 399 | encryption, it does not share the same master key with fscrypt, but manages |
| 400 | a dedicated authentication key. |
| 401 | |
| 402 | The API for providing the authentication key has yet to be defined, but the |
| 403 | key can eg. be provided by userspace through a keyring similar to the way it |
| 404 | is currently done in fscrypt. It should however be noted that the current |
| 405 | fscrypt approach has shown its flaws and the userspace API will eventually |
| 406 | change [FSCRYPT-POLICY2]. |
| 407 | |
| 408 | Nevertheless, it will be possible for a user to provide a single passphrase |
| 409 | or key in userspace that covers UBIFS authentication and encryption. This can |
| 410 | be solved by the corresponding userspace tools which derive a second key for |
| 411 | authentication in addition to the derived fscrypt master key used for |
| 412 | encryption. |
| 413 | |
| 414 | To be able to check if the proper key is available on mount, the UBIFS |
| 415 | superblock node will additionally store a hash of the authentication key. This |
| 416 | approach is similar to the approach proposed for fscrypt encryption policy v2 |
| 417 | [FSCRYPT-POLICY2]. |
| 418 | |
| 419 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 420 | Future Extensions |
| 421 | ================= |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 422 | |
| 423 | In certain cases where a vendor wants to provide an authenticated filesystem |
| 424 | image to customers, it should be possible to do so without sharing the secret |
| 425 | UBIFS authentication key. Instead, in addition the each HMAC a digital |
| 426 | signature could be stored where the vendor shares the public key alongside the |
| 427 | filesystem image. In case this filesystem has to be modified afterwards, |
| 428 | UBIFS can exchange all digital signatures with HMACs on first mount similar |
| 429 | to the way the IMA/EVM subsystem deals with such situations. The HMAC key |
| 430 | will then have to be provided beforehand in the normal way. |
| 431 | |
| 432 | |
Mauro Carvalho Chehab | 09f4c75 | 2019-07-26 09:51:14 -0300 | [diff] [blame] | 433 | References |
| 434 | ========== |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 435 | |
| 436 | [CRYPTSETUP2] http://www.saout.de/pipermail/dm-crypt/2017-November/005745.html |
| 437 | |
| 438 | [DMC-CBC-ATTACK] http://www.jakoblell.com/blog/2013/12/22/practical-malleability-attack-against-cbc-encrypted-luks-partitions/ |
| 439 | |
Mauro Carvalho Chehab | f0ba437 | 2019-06-12 14:52:43 -0300 | [diff] [blame] | 440 | [DM-INTEGRITY] https://www.kernel.org/doc/Documentation/device-mapper/dm-integrity.rst |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 441 | |
Mauro Carvalho Chehab | f0ba437 | 2019-06-12 14:52:43 -0300 | [diff] [blame] | 442 | [DM-VERITY] https://www.kernel.org/doc/Documentation/device-mapper/verity.rst |
Sascha Hauer | e453fa6 | 2018-09-07 14:36:46 +0200 | [diff] [blame] | 443 | |
| 444 | [FSCRYPT-POLICY2] https://www.spinics.net/lists/linux-ext4/msg58710.html |
| 445 | |
| 446 | [UBIFS-WP] http://www.linux-mtd.infradead.org/doc/ubifs_whitepaper.pdf |