| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | ================= |
| 4 | Inline Encryption |
| 5 | ================= |
| 6 | |
| 7 | Objective |
| 8 | ========= |
| 9 | |
| 10 | We want to support inline encryption (IE) in the kernel. |
| 11 | To allow for testing, we also want a crypto API fallback when actual |
| 12 | IE hardware is absent. We also want IE to work with layered devices |
| 13 | like dm and loopback (i.e. we want to be able to use the IE hardware |
| 14 | of the underlying devices if present, or else fall back to crypto API |
| 15 | en/decryption). |
| 16 | |
| 17 | |
| 18 | Constraints and notes |
| 19 | ===================== |
| 20 | |
| 21 | - IE hardware have a limited number of "keyslots" that can be programmed |
| 22 | with an encryption context (key, algorithm, data unit size, etc.) at any time. |
| 23 | One can specify a keyslot in a data request made to the device, and the |
| 24 | device will en/decrypt the data using the encryption context programmed into |
| 25 | that specified keyslot. When possible, we want to make multiple requests with |
| 26 | the same encryption context share the same keyslot. |
| 27 | |
| 28 | - We need a way for filesystems to specify an encryption context to use for |
| 29 | en/decrypting a struct bio, and a device driver (like UFS) needs to be able |
| 30 | to use that encryption context when it processes the bio. |
| 31 | |
| 32 | - We need a way for device drivers to expose their capabilities in a unified |
| 33 | way to the upper layers. |
| 34 | |
| 35 | |
| 36 | Design |
| 37 | ====== |
| 38 | |
| 39 | We add a struct bio_crypt_ctx to struct bio that can represent an |
| 40 | encryption context, because we need to be able to pass this encryption |
| 41 | context from the FS layer to the device driver to act upon. |
| 42 | |
| 43 | While IE hardware works on the notion of keyslots, the FS layer has no |
| 44 | knowledge of keyslots - it simply wants to specify an encryption context to |
| 45 | use while en/decrypting a bio. |
| 46 | |
| 47 | We introduce a keyslot manager (KSM) that handles the translation from |
| 48 | encryption contexts specified by the FS to keyslots on the IE hardware. |
| 49 | This KSM also serves as the way IE hardware can expose their capabilities to |
| 50 | upper layers. The generic mode of operation is: each device driver that wants |
| 51 | to support IE will construct a KSM and set it up in its struct request_queue. |
| 52 | Upper layers that want to use IE on this device can then use this KSM in |
| 53 | the device's struct request_queue to translate an encryption context into |
| 54 | a keyslot. The presence of the KSM in the request queue shall be used to mean |
| 55 | that the device supports IE. |
| 56 | |
| 57 | On the device driver end of the interface, the device driver needs to tell the |
| 58 | KSM how to actually manipulate the IE hardware in the device to do things like |
| 59 | programming the crypto key into the IE hardware into a particular keyslot. All |
| 60 | this is achieved through the :c:type:`struct keyslot_mgmt_ll_ops` that the |
| 61 | device driver passes to the KSM when creating it. |
| 62 | |
| 63 | It uses refcounts to track which keyslots are idle (either they have no |
| 64 | encryption context programmed, or there are no in-flight struct bios |
| 65 | referencing that keyslot). When a new encryption context needs a keyslot, it |
| 66 | tries to find a keyslot that has already been programmed with the same |
| 67 | encryption context, and if there is no such keyslot, it evicts the least |
| 68 | recently used idle keyslot and programs the new encryption context into that |
| 69 | one. If no idle keyslots are available, then the caller will sleep until there |
| 70 | is at least one. |
| 71 | |
| 72 | |
| 73 | Blk-crypto |
| 74 | ========== |
| 75 | |
| 76 | The above is sufficient for simple cases, but does not work if there is a |
| 77 | need for a crypto API fallback, or if we are want to use IE with layered |
| 78 | devices. To these ends, we introduce blk-crypto. Blk-crypto allows us to |
| 79 | present a unified view of encryption to the FS (so FS only needs to specify |
| 80 | an encryption context and not worry about keyslots at all), and blk-crypto |
| 81 | can decide whether to delegate the en/decryption to IE hardware or to the |
| 82 | crypto API. Blk-crypto maintains an internal KSM that serves as the crypto |
| 83 | API fallback. |
| 84 | |
| 85 | Blk-crypto needs to ensure that the encryption context is programmed into the |
| 86 | "correct" keyslot manager for IE. If a bio is submitted to a layered device |
| 87 | that eventually passes the bio down to a device that really does support IE, we |
| 88 | want the encryption context to be programmed into a keyslot for the KSM of the |
| 89 | device with IE support. However, blk-crypto does not know a priori whether a |
| 90 | particular device is the final device in the layering structure for a bio or |
| 91 | not. So in the case that a particular device does not support IE, since it is |
| 92 | possibly the final destination device for the bio, if the bio requires |
| 93 | encryption (i.e. the bio is doing a write operation), blk-crypto must fallback |
| 94 | to the crypto API *before* sending the bio to the device. |
| 95 | |
| 96 | Blk-crypto ensures that: |
| 97 | |
| 98 | - The bio's encryption context is programmed into a keyslot in the KSM of the |
| 99 | request queue that the bio is being submitted to (or the crypto API fallback |
| 100 | KSM if the request queue doesn't have a KSM), and that the ``bc_ksm`` |
| 101 | in the ``bi_crypt_context`` is set to this KSM |
| 102 | |
| 103 | - That the bio has its own individual reference to the keyslot in this KSM. |
| 104 | Once the bio passes through blk-crypto, its encryption context is programmed |
| 105 | in some KSM. The "its own individual reference to the keyslot" ensures that |
| 106 | keyslots can be released by each bio independently of other bios while |
| 107 | ensuring that the bio has a valid reference to the keyslot when, for e.g., the |
| 108 | crypto API fallback KSM in blk-crypto performs crypto on the device's behalf. |
| 109 | The individual references are ensured by increasing the refcount for the |
| 110 | keyslot in the ``bc_ksm`` when a bio with a programmed encryption |
| 111 | context is cloned. |
| 112 | |
| 113 | |
| 114 | What blk-crypto does on bio submission |
| 115 | -------------------------------------- |
| 116 | |
| 117 | **Case 1:** blk-crypto is given a bio with only an encryption context that hasn't |
| 118 | been programmed into any keyslot in any KSM (for e.g. a bio from the FS). |
| 119 | In this case, blk-crypto will program the encryption context into the KSM of the |
| 120 | request queue the bio is being submitted to (and if this KSM does not exist, |
| 121 | then it will program it into blk-crypto's internal KSM for crypto API |
| 122 | fallback). The KSM that this encryption context was programmed into is stored |
| 123 | as the ``bc_ksm`` in the bio's ``bi_crypt_context``. |
| 124 | |
| 125 | **Case 2:** blk-crypto is given a bio whose encryption context has already been |
| 126 | programmed into a keyslot in the *crypto API fallback* KSM. |
| 127 | In this case, blk-crypto does nothing; it treats the bio as not having |
| 128 | specified an encryption context. Note that we cannot do here what we will do |
| 129 | in Case 3 because we would have already encrypted the bio via the crypto API |
| 130 | by this point. |
| 131 | |
| 132 | **Case 3:** blk-crypto is given a bio whose encryption context has already been |
| 133 | programmed into a keyslot in some KSM (that is *not* the crypto API fallback |
| 134 | KSM). |
| 135 | In this case, blk-crypto first releases that keyslot from that KSM and then |
| 136 | treats the bio as in Case 1. |
| 137 | |
| 138 | This way, when a device driver is processing a bio, it can be sure that |
| 139 | the bio's encryption context has been programmed into some KSM (either the |
| 140 | device driver's request queue's KSM, or blk-crypto's crypto API fallback KSM). |
| 141 | It then simply needs to check if the bio's ``bc_ksm`` is the device's |
| 142 | request queue's KSM. If so, then it should proceed with IE. If not, it should |
| 143 | simply do nothing with respect to crypto, because some other KSM (perhaps the |
| 144 | blk-crypto crypto API fallback KSM) is handling the en/decryption. |
| 145 | |
| 146 | Blk-crypto will release the keyslot that is being held by the bio (and also |
| 147 | decrypt it if the bio is using the crypto API fallback KSM) once |
| 148 | ``bio_remaining_done`` returns true for the bio. |
| 149 | |
| 150 | |
| 151 | Layered Devices |
| 152 | =============== |
| 153 | |
| 154 | Layered devices that wish to support IE need to create their own keyslot |
| 155 | manager for their request queue, and expose whatever functionality they choose. |
| 156 | When a layered device wants to pass a bio to another layer (either by |
| 157 | resubmitting the same bio, or by submitting a clone), it doesn't need to do |
| 158 | anything special because the bio (or the clone) will once again pass through |
| 159 | blk-crypto, which will work as described in Case 3. If a layered device wants |
| 160 | for some reason to do the IO by itself instead of passing it on to a child |
| 161 | device, but it also chose to expose IE capabilities by setting up a KSM in its |
| 162 | request queue, it is then responsible for en/decrypting the data itself. In |
| 163 | such cases, the device can choose to call the blk-crypto function |
| 164 | ``blk_crypto_fallback_to_kernel_crypto_api`` (TODO: Not yet implemented), which will |
| 165 | cause the en/decryption to be done via the crypto API fallback. |
| 166 | |
| 167 | |
| 168 | Future Optimizations for layered devices |
| 169 | ======================================== |
| 170 | |
| 171 | Creating a keyslot manager for the layered device uses up memory for each |
| 172 | keyslot, and in general, a layered device (like dm-linear) merely passes the |
| 173 | request on to a "child" device, so the keyslots in the layered device itself |
| 174 | might be completely unused. We can instead define a new type of KSM; the |
| 175 | "passthrough KSM", that layered devices can use to let blk-crypto know that |
| 176 | this layered device *will* pass the bio to some child device (and hence |
| 177 | through blk-crypto again, at which point blk-crypto can program the encryption |
| 178 | context, instead of programming it into the layered device's KSM). Again, if |
| 179 | the device "lies" and decides to do the IO itself instead of passing it on to |
| 180 | a child device, it is responsible for doing the en/decryption (and can choose |
| 181 | to call ``blk_crypto_fallback_to_kernel_crypto_api``). Another use case for the |
| 182 | "passthrough KSM" is for IE devices that want to manage their own keyslots/do |
| 183 | not have a limited number of keyslots. |