€•�Œsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ+/translations/zh_CN/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/zh_TW/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/it_IT/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ja_JP/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ko_KR/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/pt_BR/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/sp_SP/block/inline-encryption”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)�”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…”�”}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒE/var/lib/git/docbuild/linux/Documentation/block/inline-encryption.rst”h´KubhŒtarget”“”)�”}”(hŒ.. _inline_encryption:”h]”h}”(h]”h ]”h"]”h$]”h&]”Œrefid”Œinline-encryption”uh1hÈh´Khhh²hh³hÇubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒInline Encryption”h]”hŒInline Encryption”…”�”}”(hhÝh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhhØh²hh³hÇh´Kubh×)�”}”(hhh]”(hÜ)�”}”(hŒ Background”h]”hŒ Background”…”�”}”(hhîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhhëh²hh³hÇh´K ubhŒ paragraph”“”)�”}”(hX…Inline encryption hardware sits logically between memory and disk, and can en/decrypt data as it goes in/out of the disk. For each I/O request, software can control exactly how the inline encryption hardware will en/decrypt the data in terms of key, algorithm, data unit size (the granularity of en/decryption), and data unit number (a value that determines the initialization vector(s)).”h]”hX…Inline encryption hardware sits logically between memory and disk, and can en/decrypt data as it goes in/out of the disk. For each I/O request, software can control exactly how the inline encryption hardware will en/decrypt the data in terms of key, algorithm, data unit size (the granularity of en/decryption), and data unit number (a value that determines the initialization vector(s)).”…”�”}”(hhþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K hhëh²hubhý)�”}”(hX}Some inline encryption hardware accepts all encryption parameters including raw keys directly in low-level I/O requests. However, most inline encryption hardware instead has a fixed number of "keyslots" and requires that the key, algorithm, and data unit size first be programmed into a keyslot. Each low-level I/O request then just contains a keyslot index and data unit number.”h]”hX�Some inline encryption hardware accepts all encryption parameters including raw keys directly in low-level I/O requests. However, most inline encryption hardware instead has a fixed number of “keyslotsâ€� and requires that the key, algorithm, and data unit size first be programmed into a keyslot. Each low-level I/O request then just contains a keyslot index and data unit number.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Khhëh²hubhý)�”}”(hXmNote that inline encryption hardware is very different from traditional crypto accelerators, which are supported through the kernel crypto API. Traditional crypto accelerators operate on memory regions, whereas inline encryption hardware operates on I/O requests. Thus, inline encryption hardware needs to be managed by the block layer, not the kernel crypto API.”h]”hXmNote that inline encryption hardware is very different from traditional crypto accelerators, which are supported through the kernel crypto API. Traditional crypto accelerators operate on memory regions, whereas inline encryption hardware operates on I/O requests. Thus, inline encryption hardware needs to be managed by the block layer, not the kernel crypto API.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Khhëh²hubhý)�”}”(hXÕInline encryption hardware is also very different from "self-encrypting drives", such as those based on the TCG Opal or ATA Security standards. Self-encrypting drives don't provide fine-grained control of encryption and provide no way to verify the correctness of the resulting ciphertext. Inline encryption hardware provides fine-grained control of encryption, including the choice of key and initialization vector for each sector, and can be tested for correctness.”h]”hXÛInline encryption hardware is also very different from “self-encrypting drivesâ€�, such as those based on the TCG Opal or ATA Security standards. Self-encrypting drives don’t provide fine-grained control of encryption and provide no way to verify the correctness of the resulting ciphertext. Inline encryption hardware provides fine-grained control of encryption, including the choice of key and initialization vector for each sector, and can be tested for correctness.”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Khhëh²hubeh}”(h]”Œ background”ah ]”h"]”Œ background”ah$]”h&]”uh1hÖhhØh²hh³hÇh´K ubh×)�”}”(hhh]”(hÜ)�”}”(hŒ Objective”h]”hŒ Objective”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhj>h²hh³hÇh´K&ubhý)�”}”(hXÐWe want to support inline encryption hardware in the kernel. The API for using such hardware should also support a fallback to the CPU, so that users only need to use a single API and more of the code can be tested without actual hardware. We also want inline encryption to work with layered devices like device-mapper and loopback (i.e. we want to be able to use the inline encryption hardware of the underlying devices if present, or else fall back to the CPU).”h]”hXÐWe want to support inline encryption hardware in the kernel. The API for using such hardware should also support a fallback to the CPU, so that users only need to use a single API and more of the code can be tested without actual hardware. We also want inline encryption to work with layered devices like device-mapper and loopback (i.e. we want to be able to use the inline encryption hardware of the underlying devices if present, or else fall back to the CPU).”…”�”}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K(hj>h²hubeh}”(h]”Œ objective”ah ]”h"]”Œ objective”ah$]”h&]”uh1hÖhhØh²hh³hÇh´K&ubh×)�”}”(hhh]”(hÜ)�”}”(hŒConstraints and notes”h]”hŒConstraints and notes”…”�”}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhjeh²hh³hÇh´K0ubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hXYWe need a way for upper layers (e.g. filesystems) to specify an encryption context to use for en/decrypting a bio, and device drivers (e.g. UFSHCD) need to be able to use that encryption context when they process the request. Encryption contexts also introduce constraints on bio merging; the block layer needs to be aware of these constraints. ”h]”hý)�”}”(hXXWe need a way for upper layers (e.g. filesystems) to specify an encryption context to use for en/decrypting a bio, and device drivers (e.g. UFSHCD) need to be able to use that encryption context when they process the request. Encryption contexts also introduce constraints on bio merging; the block layer needs to be aware of these constraints.”h]”hXXWe need a way for upper layers (e.g. filesystems) to specify an encryption context to use for en/decrypting a bio, and device drivers (e.g. UFSHCD) need to be able to use that encryption context when they process the request. Encryption contexts also introduce constraints on bio merging; the block layer needs to be aware of these constraints.”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K2hj}ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjxh²hh³hÇh´Nubj|)�”}”(hXDifferent inline encryption hardware has different supported algorithms, supported data unit sizes, maximum data unit numbers, etc. We call these properties the "crypto capabilities". We need a way for device drivers to advertise crypto capabilities to upper layers in a generic way. ”h]”hý)�”}”(hXDifferent inline encryption hardware has different supported algorithms, supported data unit sizes, maximum data unit numbers, etc. We call these properties the "crypto capabilities". We need a way for device drivers to advertise crypto capabilities to upper layers in a generic way.”h]”hX!Different inline encryption hardware has different supported algorithms, supported data unit sizes, maximum data unit numbers, etc. We call these properties the “crypto capabilitiesâ€�. We need a way for device drivers to advertise crypto capabilities to upper layers in a generic way.”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K8hj•ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjxh²hh³hÇh´Nubj|)�”}”(hXoInline encryption hardware usually (but not always) requires that keys be programmed into keyslots before being used. Since programming keyslots may be slow and there may not be very many keyslots, we shouldn't just program the key for every I/O request, but rather keep track of which keys are in the keyslots and reuse an already-programmed keyslot when possible. ”h]”hý)�”}”(hXnInline encryption hardware usually (but not always) requires that keys be programmed into keyslots before being used. Since programming keyslots may be slow and there may not be very many keyslots, we shouldn't just program the key for every I/O request, but rather keep track of which keys are in the keyslots and reuse an already-programmed keyslot when possible.”h]”hXpInline encryption hardware usually (but not always) requires that keys be programmed into keyslots before being used. Since programming keyslots may be slow and there may not be very many keyslots, we shouldn’t just program the key for every I/O request, but rather keep track of which keys are in the keyslots and reuse an already-programmed keyslot when possible.”…”�”}”(hj±h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K=hj­ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjxh²hh³hÇh´Nubj|)�”}”(hX&Upper layers typically define a specific end-of-life for crypto keys, e.g. when an encrypted directory is locked or when a crypto mapping is torn down. At these times, keys are wiped from memory. We must provide a way for upper layers to also evict keys from any keyslots they are present in. ”h]”hý)�”}”(hX%Upper layers typically define a specific end-of-life for crypto keys, e.g. when an encrypted directory is locked or when a crypto mapping is torn down. At these times, keys are wiped from memory. We must provide a way for upper layers to also evict keys from any keyslots they are present in.”h]”hX%Upper layers typically define a specific end-of-life for crypto keys, e.g. when an encrypted directory is locked or when a crypto mapping is torn down. At these times, keys are wiped from memory. We must provide a way for upper layers to also evict keys from any keyslots they are present in.”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KChjÅubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjxh²hh³hÇh´Nubj|)�”}”(hŒÔWhen possible, device-mapper devices must be able to pass through the inline encryption support of their underlying devices. However, it doesn't make sense for device-mapper devices to have keyslots themselves. ”h]”hý)�”}”(hŒÓWhen possible, device-mapper devices must be able to pass through the inline encryption support of their underlying devices. However, it doesn't make sense for device-mapper devices to have keyslots themselves.”h]”hŒÕWhen possible, device-mapper devices must be able to pass through the inline encryption support of their underlying devices. However, it doesn’t make sense for device-mapper devices to have keyslots themselves.”…”�”}”(hjáh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KHhjÝubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjxh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jvh³hÇh´K2hjeh²hubeh}”(h]”Œconstraints-and-notes”ah ]”h"]”Œconstraints and notes”ah$]”h&]”uh1hÖhhØh²hh³hÇh´K0ubh×)�”}”(hhh]”(hÜ)�”}”(hŒ Basic design”h]”hŒ Basic design”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhjh²hh³hÇh´KMubhý)�”}”(hXuWe introduce ``struct blk_crypto_key`` to represent an inline encryption key and how it will be used. This includes the type of the key (raw or hardware-wrapped); the actual bytes of the key; the size of the key; the algorithm and data unit size the key will be used with; and the number of bytes needed to represent the maximum data unit number the key will be used with.”h]”(hŒ We introduce ”…”�”}”(hjh²hh³Nh´NubhŒliteral”“”)�”}”(hŒ``struct blk_crypto_key``”h]”hŒstruct blk_crypto_key”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubhXO to represent an inline encryption key and how it will be used. This includes the type of the key (raw or hardware-wrapped); the actual bytes of the key; the size of the key; the algorithm and data unit size the key will be used with; and the number of bytes needed to represent the maximum data unit number the key will be used with.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KOhjh²hubhý)�”}”(hXZWe introduce ``struct bio_crypt_ctx`` to represent an encryption context. It contains a data unit number and a pointer to a blk_crypto_key. We add pointers to a bio_crypt_ctx to ``struct bio`` and ``struct request``; this allows users of the block layer (e.g. filesystems) to provide an encryption context when creating a bio and have it be passed down the stack for processing by the block layer and device drivers. Note that the encryption context doesn't explicitly say whether to encrypt or decrypt, as that is implicit from the direction of the bio; WRITE means encrypt, and READ means decrypt.”h]”(hŒ We introduce ”…”�”}”(hj8h²hh³Nh´Nubj)�”}”(hŒ``struct bio_crypt_ctx``”h]”hŒstruct bio_crypt_ctx”…”�”}”(hj@h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj8ubhŒ� to represent an encryption context. It contains a data unit number and a pointer to a blk_crypto_key. We add pointers to a bio_crypt_ctx to ”…”�”}”(hj8h²hh³Nh´Nubj)�”}”(hŒ``struct bio``”h]”hŒ struct bio”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj8ubhŒ and ”…”�”}”(hj8h²hh³Nh´Nubj)�”}”(hŒ``struct request``”h]”hŒstruct request”…”�”}”(hjdh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj8ubhXƒ; this allows users of the block layer (e.g. filesystems) to provide an encryption context when creating a bio and have it be passed down the stack for processing by the block layer and device drivers. Note that the encryption context doesn’t explicitly say whether to encrypt or decrypt, as that is implicit from the direction of the bio; WRITE means encrypt, and READ means decrypt.”…”�”}”(hj8h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KUhjh²hubhý)�”}”(hXøWe also introduce ``struct blk_crypto_profile`` to contain all generic inline encryption-related state for a particular inline encryption device. The blk_crypto_profile serves as the way that drivers for inline encryption hardware advertise their crypto capabilities and provide certain functions (e.g., functions to program and evict keys) to upper layers. Each device driver that wants to support inline encryption will construct a blk_crypto_profile, then associate it with the disk's request_queue.”h]”(hŒWe also introduce ”…”�”}”(hj|h²hh³Nh´Nubj)�”}”(hŒ``struct blk_crypto_profile``”h]”hŒstruct blk_crypto_profile”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj|ubhXË to contain all generic inline encryption-related state for a particular inline encryption device. The blk_crypto_profile serves as the way that drivers for inline encryption hardware advertise their crypto capabilities and provide certain functions (e.g., functions to program and evict keys) to upper layers. Each device driver that wants to support inline encryption will construct a blk_crypto_profile, then associate it with the disk’s request_queue.”…”�”}”(hj|h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K^hjh²hubhý)�”}”(hX/The blk_crypto_profile also manages the hardware's keyslots, when applicable. This happens in the block layer, so that users of the block layer can just specify encryption contexts and don't need to know about keyslots at all, nor do device drivers need to care about most details of keyslot management.”h]”hX3The blk_crypto_profile also manages the hardware’s keyslots, when applicable. This happens in the block layer, so that users of the block layer can just specify encryption contexts and don’t need to know about keyslots at all, nor do device drivers need to care about most details of keyslot management.”…”�”}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Kfhjh²hubhý)�”}”(hX×Specifically, for each keyslot, the block layer (via the blk_crypto_profile) keeps track of which blk_crypto_key that keyslot contains (if any), and how many in-flight I/O requests are using it. When the block layer creates a ``struct request`` for a bio that has an encryption context, it grabs a keyslot that already contains the key if possible. Otherwise it waits for an idle keyslot (a keyslot that isn't in-use by any I/O), then programs the key into the least-recently-used idle keyslot using the function the device driver provided. In both cases, the resulting keyslot is stored in the ``crypt_keyslot`` field of the request, where it is then accessible to device drivers and is released after the request completes.”h]”(hŒãSpecifically, for each keyslot, the block layer (via the blk_crypto_profile) keeps track of which blk_crypto_key that keyslot contains (if any), and how many in-flight I/O requests are using it. When the block layer creates a ”…”�”}”(hjªh²hh³Nh´Nubj)�”}”(hŒ``struct request``”h]”hŒstruct request”…”�”}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjªubhXb for a bio that has an encryption context, it grabs a keyslot that already contains the key if possible. Otherwise it waits for an idle keyslot (a keyslot that isn’t in-use by any I/O), then programs the key into the least-recently-used idle keyslot using the function the device driver provided. In both cases, the resulting keyslot is stored in the ”…”�”}”(hjªh²hh³Nh´Nubj)�”}”(hŒ``crypt_keyslot``”h]”hŒ crypt_keyslot”…”�”}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjªubhŒq field of the request, where it is then accessible to device drivers and is released after the request completes.”…”�”}”(hjªh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Kkhjh²hubhý)�”}”(hX)``struct request`` also contains a pointer to the original bio_crypt_ctx. Requests can be built from multiple bios, and the block layer must take the encryption context into account when trying to merge bios and requests. For two bios/requests to be merged, they must have compatible encryption contexts: both unencrypted, or both encrypted with the same key and contiguous data unit numbers. Only the encryption context for the first bio in a request is retained, since the remaining bios have been verified to be merge-compatible with the first bio.”h]”(j)�”}”(hŒ``struct request``”h]”hŒstruct request”…”�”}”(hjàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÜubhX also contains a pointer to the original bio_crypt_ctx. Requests can be built from multiple bios, and the block layer must take the encryption context into account when trying to merge bios and requests. For two bios/requests to be merged, they must have compatible encryption contexts: both unencrypted, or both encrypted with the same key and contiguous data unit numbers. Only the encryption context for the first bio in a request is retained, since the remaining bios have been verified to be merge-compatible with the first bio.”…”�”}”(hjÜh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Kvhjh²hubhý)�”}”(hX/To make it possible for inline encryption to work with request_queue based layered devices, when a request is cloned, its encryption context is cloned as well. When the cloned request is submitted, it is then processed as usual; this includes getting a keyslot from the clone's target device if needed.”h]”hX1To make it possible for inline encryption to work with request_queue based layered devices, when a request is cloned, its encryption context is cloned as well. When the cloned request is submitted, it is then processed as usual; this includes getting a keyslot from the clone’s target device if needed.”…”�”}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Khjh²hubeh}”(h]”Œ basic-design”ah ]”h"]”Œ basic design”ah$]”h&]”uh1hÖhhØh²hh³hÇh´KMubh×)�”}”(hhh]”(hÜ)�”}”(hŒblk-crypto-fallback”h]”hŒblk-crypto-fallback”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhjh²hh³hÇh´K…ubhý)�”}”(hXUIt is desirable for the inline encryption support of upper layers (e.g. filesystems) to be testable without real inline encryption hardware, and likewise for the block layer's keyslot management logic. It is also desirable to allow upper layers to just always use inline encryption rather than have to implement encryption in multiple ways.”h]”hXWIt is desirable for the inline encryption support of upper layers (e.g. filesystems) to be testable without real inline encryption hardware, and likewise for the block layer’s keyslot management logic. It is also desirable to allow upper layers to just always use inline encryption rather than have to implement encryption in multiple ways.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K‡hjh²hubhý)�”}”(hX¿Therefore, we also introduce *blk-crypto-fallback*, which is an implementation of inline encryption using the kernel crypto API. blk-crypto-fallback is built into the block layer, so it works on any block device without any special setup. Essentially, when a bio with an encryption context is submitted to a block_device that doesn't support that encryption context, the block layer will handle en/decryption of the bio using blk-crypto-fallback.”h]”(hŒTherefore, we also introduce ”…”�”}”(hj-h²hh³Nh´NubhŒemphasis”“”)�”}”(hŒ*blk-crypto-fallback*”h]”hŒblk-crypto-fallback”…”�”}”(hj7h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j5hj-ubhX�, which is an implementation of inline encryption using the kernel crypto API. blk-crypto-fallback is built into the block layer, so it works on any block device without any special setup. Essentially, when a bio with an encryption context is submitted to a block_device that doesn’t support that encryption context, the block layer will handle en/decryption of the bio using blk-crypto-fallback.”…”�”}”(hj-h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K�hjh²hubhý)�”}”(hXÂFor encryption, the data cannot be encrypted in-place, as callers usually rely on it being unmodified. Instead, blk-crypto-fallback allocates bounce pages, fills a new bio with those bounce pages, encrypts the data into those bounce pages, and submits that "bounce" bio. When the bounce bio completes, blk-crypto-fallback completes the original bio. If the original bio is too large, multiple bounce bios may be required; see the code for details.”h]”hXÆFor encryption, the data cannot be encrypted in-place, as callers usually rely on it being unmodified. Instead, blk-crypto-fallback allocates bounce pages, fills a new bio with those bounce pages, encrypts the data into those bounce pages, and submits that “bounceâ€� bio. When the bounce bio completes, blk-crypto-fallback completes the original bio. If the original bio is too large, multiple bounce bios may be required; see the code for details.”…”�”}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K”hjh²hubhý)�”}”(hXìFor decryption, blk-crypto-fallback "wraps" the bio's completion callback (``bi_end_io``) and private data (``bi_private``) with its own, unsets the bio's encryption context, then submits the bio. If the read completes successfully, blk-crypto-fallback restores the bio's original completion callback and private data, then decrypts the bio's data in-place using the kernel crypto API. Decryption happens from a workqueue, as it may sleep. Afterwards, blk-crypto-fallback completes the bio.”h]”(hŒQFor decryption, blk-crypto-fallback “wrapsâ€� the bio’s completion callback (”…”�”}”(hj]h²hh³Nh´Nubj)�”}”(hŒ ``bi_end_io``”h]”hŒ bi_end_io”…”�”}”(hjeh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj]ubhŒ) and private data (”…”�”}”(hj]h²hh³Nh´Nubj)�”}”(hŒ``bi_private``”h]”hŒ bi_private”…”�”}”(hjwh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj]ubhXx) with its own, unsets the bio’s encryption context, then submits the bio. If the read completes successfully, blk-crypto-fallback restores the bio’s original completion callback and private data, then decrypts the bio’s data in-place using the kernel crypto API. Decryption happens from a workqueue, as it may sleep. Afterwards, blk-crypto-fallback completes the bio.”…”�”}”(hj]h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K›hjh²hubhý)�”}”(hŒšIn both cases, the bios that blk-crypto-fallback submits no longer have an encryption context. Therefore, lower layers only see standard unencrypted I/O.”h]”hŒšIn both cases, the bios that blk-crypto-fallback submits no longer have an encryption context. Therefore, lower layers only see standard unencrypted I/O.”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K£hjh²hubhý)�”}”(hX“blk-crypto-fallback also defines its own blk_crypto_profile and has its own "keyslots"; its keyslots contain ``struct crypto_skcipher`` objects. The reason for this is twofold. First, it allows the keyslot management logic to be tested without actual inline encryption hardware. Second, similar to actual inline encryption hardware, the crypto API doesn't accept keys directly in requests but rather requires that keys be set ahead of time, and setting keys can be expensive; moreover, allocating a crypto_skcipher can't happen on the I/O path at all due to the locks it takes. Therefore, the concept of keyslots still makes sense for blk-crypto-fallback.”h]”(hŒqblk-crypto-fallback also defines its own blk_crypto_profile and has its own “keyslotsâ€�; its keyslots contain ”…”�”}”(hj�h²hh³Nh´Nubj)�”}”(hŒ``struct crypto_skcipher``”h]”hŒstruct crypto_skcipher”…”�”}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj�ubhX objects. The reason for this is twofold. First, it allows the keyslot management logic to be tested without actual inline encryption hardware. Second, similar to actual inline encryption hardware, the crypto API doesn’t accept keys directly in requests but rather requires that keys be set ahead of time, and setting keys can be expensive; moreover, allocating a crypto_skcipher can’t happen on the I/O path at all due to the locks it takes. Therefore, the concept of keyslots still makes sense for blk-crypto-fallback.”…”�”}”(hj�h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K¦hjh²hubhý)�”}”(hXiNote that regardless of whether real inline encryption hardware or blk-crypto-fallback is used, the ciphertext written to disk (and hence the on-disk format of data) will be the same (assuming that both the inline encryption hardware's implementation and the kernel crypto API's implementation of the algorithm being used adhere to spec and function correctly).”h]”hXmNote that regardless of whether real inline encryption hardware or blk-crypto-fallback is used, the ciphertext written to disk (and hence the on-disk format of data) will be the same (assuming that both the inline encryption hardware’s implementation and the kernel crypto API’s implementation of the algorithm being used adhere to spec and function correctly).”…”�”}”(hj½h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K°hjh²hubhý)�”}”(hŒblk-crypto-fallback is optional and is controlled by the ``CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK`` kernel configuration option.”h]”(hŒ9blk-crypto-fallback is optional and is controlled by the ”…”�”}”(hjËh²hh³Nh´Nubj)�”}”(hŒ)``CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK``”h]”hŒ%CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK”…”�”}”(hjÓh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjËubhŒ kernel configuration option.”…”�”}”(hjËh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K¶hjh²hubeh}”(h]”Œblk-crypto-fallback”ah ]”h"]”Œblk-crypto-fallback”ah$]”h&]”uh1hÖhhØh²hh³hÇh´K…ubh×)�”}”(hhh]”(hÜ)�”}”(hŒ)API presented to users of the block layer”h]”hŒ)API presented to users of the block layer”…”�”}”(hjöh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhjóh²hh³hÇh´Kºubhý)�”}”(hŒF``blk_crypto_init_key()`` allows users to initialize a blk_crypto_key.”h]”(j)�”}”(hŒ``blk_crypto_init_key()``”h]”hŒblk_crypto_init_key()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjubhŒ- allows users to initialize a blk_crypto_key.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K¼hjóh²hubhý)�”}”(hX2Users must call ``blk_crypto_start_using_key()`` before actually starting to use a blk_crypto_key on a block_device. This is needed to initialize blk-crypto-fallback if it will be needed. This must not be called from the data path, as this may have to allocate resources, which may deadlock in that case.”h]”(hŒUsers must call ”…”�”}”(hj h²hh³Nh´Nubj)�”}”(hŒ ``blk_crypto_start_using_key()``”h]”hŒblk_crypto_start_using_key()”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj ubhX before actually starting to use a blk_crypto_key on a block_device. This is needed to initialize blk-crypto-fallback if it will be needed. This must not be called from the data path, as this may have to allocate resources, which may deadlock in that case.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K¾hjóh²hubhý)�”}”(hXtNext, to attach an encryption context to a bio, users should call ``bio_crypt_set_ctx()``. This function allocates a bio_crypt_ctx and attaches it to a bio, given the blk_crypto_key and the data unit number that will be used for en/decryption. Users don't need to worry about freeing the bio_crypt_ctx later, as that happens automatically when the bio is freed or reset.”h]”(hŒBNext, to attach an encryption context to a bio, users should call ”…”�”}”(hj@h²hh³Nh´Nubj)�”}”(hŒ``bio_crypt_set_ctx()``”h]”hŒbio_crypt_set_ctx()”…”�”}”(hjHh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj@ubhX. This function allocates a bio_crypt_ctx and attaches it to a bio, given the blk_crypto_key and the data unit number that will be used for en/decryption. Users don’t need to worry about freeing the bio_crypt_ctx later, as that happens automatically when the bio is freed or reset.”…”�”}”(hj@h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KÃhjóh²hubhý)�”}”(hX7To submit a bio that uses inline encryption, users must call ``blk_crypto_submit_bio()`` instead of the usual ``submit_bio()``. This will submit the bio to the underlying driver if it supports inline crypto, or else call the blk-crypto fallback routines before submitting normal bios to the underlying drivers.”h]”(hŒ=To submit a bio that uses inline encryption, users must call ”…”�”}”(hj`h²hh³Nh´Nubj)�”}”(hŒ``blk_crypto_submit_bio()``”h]”hŒblk_crypto_submit_bio()”…”�”}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj`ubhŒ instead of the usual ”…”�”}”(hj`h²hh³Nh´Nubj)�”}”(hŒ``submit_bio()``”h]”hŒ submit_bio()”…”�”}”(hjzh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj`ubhŒ¹. This will submit the bio to the underlying driver if it supports inline crypto, or else call the blk-crypto fallback routines before submitting normal bios to the underlying drivers.”…”�”}”(hj`h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KÉhjóh²hubhý)�”}”(hXFinally, when done using inline encryption with a blk_crypto_key on a block_device, users must call ``blk_crypto_evict_key()``. This ensures that the key is evicted from all keyslots it may be programmed into and unlinked from any kernel data structures it may be linked into.”h]”(hŒdFinally, when done using inline encryption with a blk_crypto_key on a block_device, users must call ”…”�”}”(hj’h²hh³Nh´Nubj)�”}”(hŒ``blk_crypto_evict_key()``”h]”hŒblk_crypto_evict_key()”…”�”}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj’ubhŒ—. This ensures that the key is evicted from all keyslots it may be programmed into and unlinked from any kernel data structures it may be linked into.”…”�”}”(hj’h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KÏhjóh²hubhý)�”}”(hŒZIn summary, for users of the block layer, the lifecycle of a blk_crypto_key is as follows:”h]”hŒZIn summary, for users of the block layer, the lifecycle of a blk_crypto_key is as follows:”…”�”}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KÔhjóh²hubhŒenumerated_list”“”)�”}”(hhh]”(j|)�”}”(hŒ``blk_crypto_init_key()``”h]”hý)�”}”(hjÇh]”j)�”}”(hjÇh]”hŒblk_crypto_init_key()”…”�”}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjÉubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´K×hjÅubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjÂh²hh³hÇh´Nubj|)�”}”(hŒ ``blk_crypto_start_using_key()``”h]”hý)�”}”(hjçh]”j)�”}”(hjçh]”hŒblk_crypto_start_using_key()”…”�”}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjéubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KØhjåubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjÂh²hh³hÇh´Nubj|)�”}”(hŒ0``bio_crypt_set_ctx()`` (potentially many times)”h]”hý)�”}”(hjh]”(j)�”}”(hŒ``bio_crypt_set_ctx()``”h]”hŒbio_crypt_set_ctx()”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj ubhŒ (potentially many times)”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KÙhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjÂh²hh³hÇh´Nubj|)�”}”(hŒ8``blk_crypto_evict_key()`` (after all I/O has completed)”h]”hý)�”}”(hj,h]”(j)�”}”(hŒ``blk_crypto_evict_key()``”h]”hŒblk_crypto_evict_key()”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj.ubhŒ (after all I/O has completed)”…”�”}”(hj.h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´KÚhj*ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjÂh²hh³hÇh´Nubj|)�”}”(hŒ | ----------------------------- | | Inline encryption key Software secret”h]”hX Hardware-wrapped key | | | ----------------------------- | | Inline encryption key Software secret”…”�”}”hjX sbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jV h³hÇh´M™hj7 h²hubhý)�”}”(hŒThe components are:”h]”hŒThe components are:”…”�”}”(hjf h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M¢hj7 h²hubjw)�”}”(hhh]”(j|)�”}”(hX'*Hardware-wrapped key*: a key for the hardware's KDF (Key Derivation Function), in ephemerally-wrapped form. The key wrapping algorithm is a hardware implementation detail that doesn't impact kernel operation, but a strong authenticated encryption algorithm such as AES-256-GCM is recommended. ”h]”hý)�”}”(hX&*Hardware-wrapped key*: a key for the hardware's KDF (Key Derivation Function), in ephemerally-wrapped form. The key wrapping algorithm is a hardware implementation detail that doesn't impact kernel operation, but a strong authenticated encryption algorithm such as AES-256-GCM is recommended.”h]”(j6)�”}”(hŒ*Hardware-wrapped key*”h]”hŒHardware-wrapped key”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j5hj{ ubhX: a key for the hardware’s KDF (Key Derivation Function), in ephemerally-wrapped form. The key wrapping algorithm is a hardware implementation detail that doesn’t impact kernel operation, but a strong authenticated encryption algorithm such as AES-256-GCM is recommended.”…”�”}”(hj{ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M¤hjw ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjt h²hh³hÇh´Nubj|)�”}”(hXá*Hardware KDF*: a KDF (Key Derivation Function) which the hardware uses to derive subkeys after unwrapping the wrapped key. The hardware's choice of KDF doesn't impact kernel operation, but it does need to be known for testing purposes, and it's also assumed to have at least a 256-bit security strength. All known hardware uses the SP800-108 KDF in Counter Mode with AES-256-CMAC, with a particular choice of labels and contexts; new hardware should use this already-vetted KDF. ”h]”hý)�”}”(hXà*Hardware KDF*: a KDF (Key Derivation Function) which the hardware uses to derive subkeys after unwrapping the wrapped key. The hardware's choice of KDF doesn't impact kernel operation, but it does need to be known for testing purposes, and it's also assumed to have at least a 256-bit security strength. All known hardware uses the SP800-108 KDF in Counter Mode with AES-256-CMAC, with a particular choice of labels and contexts; new hardware should use this already-vetted KDF.”h]”(j6)�”}”(hŒ*Hardware KDF*”h]”hŒ Hardware KDF”…”�”}”(hj¥ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j5hj¡ ubhXØ: a KDF (Key Derivation Function) which the hardware uses to derive subkeys after unwrapping the wrapped key. The hardware’s choice of KDF doesn’t impact kernel operation, but it does need to be known for testing purposes, and it’s also assumed to have at least a 256-bit security strength. All known hardware uses the SP800-108 KDF in Counter Mode with AES-256-CMAC, with a particular choice of labels and contexts; new hardware should use this already-vetted KDF.”…”�”}”(hj¡ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M©hj� ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjt h²hh³hÇh´Nubj|)�”}”(hXx*Inline encryption key*: a derived key which the hardware directly provisions to a keyslot of the inline encryption hardware, without exposing it to software. In all known hardware, this will always be an AES-256-XTS key. However, in principle other encryption algorithms could be supported too. Hardware must derive distinct subkeys for each supported encryption algorithm. ”h]”hý)�”}”(hXw*Inline encryption key*: a derived key which the hardware directly provisions to a keyslot of the inline encryption hardware, without exposing it to software. In all known hardware, this will always be an AES-256-XTS key. However, in principle other encryption algorithms could be supported too. Hardware must derive distinct subkeys for each supported encryption algorithm.”h]”(j6)�”}”(hŒ*Inline encryption key*”h]”hŒInline encryption key”…”�”}”(hjË h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j5hjÇ ubhX`: a derived key which the hardware directly provisions to a keyslot of the inline encryption hardware, without exposing it to software. In all known hardware, this will always be an AES-256-XTS key. However, in principle other encryption algorithms could be supported too. Hardware must derive distinct subkeys for each supported encryption algorithm.”…”�”}”(hjÇ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M±hjà ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjt h²hh³hÇh´Nubj|)�”}”(hX*Software secret*: a derived key which the hardware returns to software so that software can use it for cryptographic tasks that can't use inline encryption. This value is cryptographically isolated from the inline encryption key, i.e. knowing one doesn't reveal the other. (The KDF ensures this.) Currently, the software secret is always 32 bytes and thus is suitable for cryptographic applications that require up to a 256-bit security strength. Some use cases (e.g. full-disk encryption) won't require the software secret. ”h]”hý)�”}”(hX*Software secret*: a derived key which the hardware returns to software so that software can use it for cryptographic tasks that can't use inline encryption. This value is cryptographically isolated from the inline encryption key, i.e. knowing one doesn't reveal the other. (The KDF ensures this.) Currently, the software secret is always 32 bytes and thus is suitable for cryptographic applications that require up to a 256-bit security strength. Some use cases (e.g. full-disk encryption) won't require the software secret.”h]”(j6)�”}”(hŒ*Software secret*”h]”hŒSoftware secret”…”�”}”(hjñ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j5hjí ubhX: a derived key which the hardware returns to software so that software can use it for cryptographic tasks that can’t use inline encryption. This value is cryptographically isolated from the inline encryption key, i.e. knowing one doesn’t reveal the other. (The KDF ensures this.) Currently, the software secret is always 32 bytes and thus is suitable for cryptographic applications that require up to a 256-bit security strength. Some use cases (e.g. full-disk encryption) won’t require the software secret.”…”�”}”(hjí h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M·hjé ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjt h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jûjüuh1jvh³hÇh´M¤hj7 h²hubhý)�”}”(hX�Example: in the case of fscrypt, the fscrypt master key (the key that protects a particular set of encrypted directories) is made hardware-wrapped. The inline encryption key is used as the file contents encryption key, while the software secret (rather than the master key directly) is used to key fscrypt's KDF (HKDF-SHA512) to derive other subkeys such as filenames encryption keys.”h]”hXƒExample: in the case of fscrypt, the fscrypt master key (the key that protects a particular set of encrypted directories) is made hardware-wrapped. The inline encryption key is used as the file contents encryption key, while the software secret (rather than the master key directly) is used to key fscrypt’s KDF (HKDF-SHA512) to derive other subkeys such as filenames encryption keys.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M¿hj7 h²hubhý)�”}”(hXoNote that currently this design assumes a single inline encryption key per hardware-wrapped key, without any further key derivation. Thus, in the case of fscrypt, currently hardware-wrapped keys are only compatible with the "inline encryption optimized" settings, which use one file contents encryption key per encryption policy rather than one per file. This design could be extended to make the hardware derive per-file keys using per-file nonces passed down the storage stack, and in fact some hardware already supports this; future work is planned to remove this limitation by adding the corresponding kernel support.”h]”hXsNote that currently this design assumes a single inline encryption key per hardware-wrapped key, without any further key derivation. Thus, in the case of fscrypt, currently hardware-wrapped keys are only compatible with the “inline encryption optimizedâ€� settings, which use one file contents encryption key per encryption policy rather than one per file. This design could be extended to make the hardware derive per-file keys using per-file nonces passed down the storage stack, and in fact some hardware already supports this; future work is planned to remove this limitation by adding the corresponding kernel support.”…”�”}”(hj# h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MÅhj7 h²hubeh}”(h]”Œ key-hierarchy”ah ]”h"]”Œ key hierarchy”ah$]”h&]”uh1hÖhjŠh²hh³hÇh´M•ubh×)�”}”(hhh]”(hÜ)�”}”(hŒKernel support”h]”hŒKernel support”…”�”}”(hj< h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhj9 h²hh³hÇh´MÏubhý)�”}”(hŒàThe inline encryption support of the kernel's block layer ("blk-crypto") has been extended to support hardware-wrapped keys as an alternative to raw keys, when hardware support is available. This works in the following way:”h]”hŒæThe inline encryption support of the kernel’s block layer (“blk-cryptoâ€�) has been extended to support hardware-wrapped keys as an alternative to raw keys, when hardware support is available. This works in the following way:”…”�”}”(hjJ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MÑhj9 h²hubjw)�”}”(hhh]”(j|)�”}”(hŒÉA ``key_types_supported`` field is added to the crypto capabilities in ``struct blk_crypto_profile``. This allows device drivers to declare that they support raw keys, hardware-wrapped keys, or both. ”h]”hý)�”}”(hŒÈA ``key_types_supported`` field is added to the crypto capabilities in ``struct blk_crypto_profile``. This allows device drivers to declare that they support raw keys, hardware-wrapped keys, or both.”h]”(hŒA ”…”�”}”(hj_ h²hh³Nh´Nubj)�”}”(hŒ``key_types_supported``”h]”hŒkey_types_supported”…”�”}”(hjg h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj_ ubhŒ. field is added to the crypto capabilities in ”…”�”}”(hj_ h²hh³Nh´Nubj)�”}”(hŒ``struct blk_crypto_profile``”h]”hŒstruct blk_crypto_profile”…”�”}”(hjy h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj_ ubhŒd. This allows device drivers to declare that they support raw keys, hardware-wrapped keys, or both.”…”�”}”(hj_ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MÕhj[ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjX h²hh³hÇh´Nubj|)�”}”(hXI``struct blk_crypto_key`` can now contain a hardware-wrapped key as an alternative to a raw key; a ``key_type`` field is added to ``struct blk_crypto_config`` to distinguish between the different key types. This allows users of blk-crypto to en/decrypt data using a hardware-wrapped key in a way very similar to using a raw key. ”h]”hý)�”}”(hXH``struct blk_crypto_key`` can now contain a hardware-wrapped key as an alternative to a raw key; a ``key_type`` field is added to ``struct blk_crypto_config`` to distinguish between the different key types. This allows users of blk-crypto to en/decrypt data using a hardware-wrapped key in a way very similar to using a raw key.”h]”(j)�”}”(hŒ``struct blk_crypto_key``”h]”hŒstruct blk_crypto_key”…”�”}”(hjŸ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj› ubhŒJ can now contain a hardware-wrapped key as an alternative to a raw key; a ”…”�”}”(hj› h²hh³Nh´Nubj)�”}”(hŒ ``key_type``”h]”hŒkey_type”…”�”}”(hj± h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj› ubhŒ field is added to ”…”�”}”(hj› h²hh³Nh´Nubj)�”}”(hŒ``struct blk_crypto_config``”h]”hŒstruct blk_crypto_config”…”�”}”(hjà h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj› ubhŒª to distinguish between the different key types. This allows users of blk-crypto to en/decrypt data using a hardware-wrapped key in a way very similar to using a raw key.”…”�”}”(hj› h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MÙhj— ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjX h²hh³hÇh´Nubj|)�”}”(hŒåA new method ``blk_crypto_ll_ops::derive_sw_secret`` is added. Device drivers that support hardware-wrapped keys must implement this method. Users of blk-crypto can call ``blk_crypto_derive_sw_secret()`` to access this method. ”h]”hý)�”}”(hŒäA new method ``blk_crypto_ll_ops::derive_sw_secret`` is added. Device drivers that support hardware-wrapped keys must implement this method. Users of blk-crypto can call ``blk_crypto_derive_sw_secret()`` to access this method.”h]”(hŒ A new method ”…”�”}”(hjå h²hh³Nh´Nubj)�”}”(hŒ'``blk_crypto_ll_ops::derive_sw_secret``”h]”hŒ#blk_crypto_ll_ops::derive_sw_secret”…”�”}”(hjí h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjå ubhŒx is added. Device drivers that support hardware-wrapped keys must implement this method. Users of blk-crypto can call ”…”�”}”(hjå h²hh³Nh´Nubj)�”}”(hŒ!``blk_crypto_derive_sw_secret()``”h]”hŒblk_crypto_derive_sw_secret()”…”�”}”(hjÿ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjå ubhŒ to access this method.”…”�”}”(hjå h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Mßhjá ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjX h²hh³hÇh´Nubj|)�”}”(hX)The programming and eviction of hardware-wrapped keys happens via ``blk_crypto_ll_ops::keyslot_program`` and ``blk_crypto_ll_ops::keyslot_evict``, just like it does for raw keys. If a driver supports hardware-wrapped keys, then it must handle hardware-wrapped keys being passed to these methods. ”h]”hý)�”}”(hX(The programming and eviction of hardware-wrapped keys happens via ``blk_crypto_ll_ops::keyslot_program`` and ``blk_crypto_ll_ops::keyslot_evict``, just like it does for raw keys. If a driver supports hardware-wrapped keys, then it must handle hardware-wrapped keys being passed to these methods.”h]”(hŒBThe programming and eviction of hardware-wrapped keys happens via ”…”�”}”(hj! h²hh³Nh´Nubj)�”}”(hŒ&``blk_crypto_ll_ops::keyslot_program``”h]”hŒ"blk_crypto_ll_ops::keyslot_program”…”�”}”(hj) h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj! ubhŒ and ”…”�”}”(hj! h²hh³Nh´Nubj)�”}”(hŒ$``blk_crypto_ll_ops::keyslot_evict``”h]”hŒ blk_crypto_ll_ops::keyslot_evict”…”�”}”(hj; h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj! ubhŒ—, just like it does for raw keys. If a driver supports hardware-wrapped keys, then it must handle hardware-wrapped keys being passed to these methods.”…”�”}”(hj! h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Mãhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hjX h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jûjüuh1jvh³hÇh´MÕhj9 h²hubhý)�”}”(hŒ•blk-crypto-fallback doesn't support hardware-wrapped keys. Therefore, hardware-wrapped keys can only be used with actual inline encryption hardware.”h]”hŒ—blk-crypto-fallback doesn’t support hardware-wrapped keys. Therefore, hardware-wrapped keys can only be used with actual inline encryption hardware.”…”�”}”(hj_ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Méhj9 h²hubhý)�”}”(hŒáAll the above deals with hardware-wrapped keys in ephemerally-wrapped form only. To get such keys in the first place, new block device ioctls have been added to provide a generic interface to creating and preparing such keys:”h]”hŒáAll the above deals with hardware-wrapped keys in ephemerally-wrapped form only. To get such keys in the first place, new block device ioctls have been added to provide a generic interface to creating and preparing such keys:”…”�”}”(hjm h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Mìhj9 h²hubjw)�”}”(hhh]”(j|)�”}”(hXð``BLKCRYPTOIMPORTKEY`` converts a raw key to long-term wrapped form. It takes in a pointer to a ``struct blk_crypto_import_key_arg``. The caller must set ``raw_key_ptr`` and ``raw_key_size`` to the pointer and size (in bytes) of the raw key to import. On success, ``BLKCRYPTOIMPORTKEY`` returns 0 and writes the resulting long-term wrapped key blob to the buffer pointed to by ``lt_key_ptr``, which is of maximum size ``lt_key_size``. It also updates ``lt_key_size`` to be the actual size of the key. On failure, it returns -1 and sets errno. An errno of ``EOPNOTSUPP`` indicates that the block device does not support hardware-wrapped keys. An errno of ``EOVERFLOW`` indicates that the output buffer did not have enough space for the key blob. ”h]”hý)�”}”(hXï``BLKCRYPTOIMPORTKEY`` converts a raw key to long-term wrapped form. It takes in a pointer to a ``struct blk_crypto_import_key_arg``. The caller must set ``raw_key_ptr`` and ``raw_key_size`` to the pointer and size (in bytes) of the raw key to import. On success, ``BLKCRYPTOIMPORTKEY`` returns 0 and writes the resulting long-term wrapped key blob to the buffer pointed to by ``lt_key_ptr``, which is of maximum size ``lt_key_size``. It also updates ``lt_key_size`` to be the actual size of the key. On failure, it returns -1 and sets errno. An errno of ``EOPNOTSUPP`` indicates that the block device does not support hardware-wrapped keys. An errno of ``EOVERFLOW`` indicates that the output buffer did not have enough space for the key blob.”h]”(j)�”}”(hŒ``BLKCRYPTOIMPORTKEY``”h]”hŒBLKCRYPTOIMPORTKEY”…”�”}”(hj† h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒK converts a raw key to long-term wrapped form. It takes in a pointer to a ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ$``struct blk_crypto_import_key_arg``”h]”hŒ struct blk_crypto_import_key_arg”…”�”}”(hj˜ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ. The caller must set ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``raw_key_ptr``”h]”hŒ raw_key_ptr”…”�”}”(hjª h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ and ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``raw_key_size``”h]”hŒ raw_key_size”…”�”}”(hj¼ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒK to the pointer and size (in bytes) of the raw key to import. On success, ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOIMPORTKEY``”h]”hŒBLKCRYPTOIMPORTKEY”…”�”}”(hjÎ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ[ returns 0 and writes the resulting long-term wrapped key blob to the buffer pointed to by ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``lt_key_ptr``”h]”hŒ lt_key_ptr”…”�”}”(hjà h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ, which is of maximum size ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``lt_key_size``”h]”hŒ lt_key_size”…”�”}”(hjò h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ. It also updates ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``lt_key_size``”h]”hŒ lt_key_size”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ[ to be the actual size of the key. On failure, it returns -1 and sets errno. An errno of ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``EOPNOTSUPP``”h]”hŒ EOPNOTSUPP”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒV indicates that the block device does not support hardware-wrapped keys. An errno of ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ ``EOVERFLOW``”h]”hŒ EOVERFLOW”…”�”}”(hj( h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒM indicates that the output buffer did not have enough space for the key blob.”…”�”}”(hj‚ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Mðhj~ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hj{ h²hh³hÇh´Nubj|)�”}”(hŒÀ``BLKCRYPTOGENERATEKEY`` is like ``BLKCRYPTOIMPORTKEY``, but it has the hardware generate the key instead of importing one. It takes in a pointer to a ``struct blk_crypto_generate_key_arg``. ”h]”hý)�”}”(hŒ¿``BLKCRYPTOGENERATEKEY`` is like ``BLKCRYPTOIMPORTKEY``, but it has the hardware generate the key instead of importing one. It takes in a pointer to a ``struct blk_crypto_generate_key_arg``.”h]”(j)�”}”(hŒ``BLKCRYPTOGENERATEKEY``”h]”hŒBLKCRYPTOGENERATEKEY”…”�”}”(hjN h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjJ ubhŒ is like ”…”�”}”(hjJ h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOIMPORTKEY``”h]”hŒBLKCRYPTOIMPORTKEY”…”�”}”(hj` h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjJ ubhŒa, but it has the hardware generate the key instead of importing one. It takes in a pointer to a ”…”�”}”(hjJ h²hh³Nh´Nubj)�”}”(hŒ&``struct blk_crypto_generate_key_arg``”h]”hŒ"struct blk_crypto_generate_key_arg”…”�”}”(hjr h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjJ ubhŒ.”…”�”}”(hjJ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MûhjF ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hj{ h²hh³hÇh´Nubj|)�”}”(hX ``BLKCRYPTOPREPAREKEY`` converts a key from long-term wrapped form to ephemerally-wrapped form. It takes in a pointer to a ``struct blk_crypto_prepare_key_arg``. The caller must set ``lt_key_ptr`` and ``lt_key_size`` to the pointer and size (in bytes) of the long-term wrapped key blob to convert. On success, ``BLKCRYPTOPREPAREKEY`` returns 0 and writes the resulting ephemerally-wrapped key blob to the buffer pointed to by ``eph_key_ptr``, which is of maximum size ``eph_key_size``. It also updates ``eph_key_size`` to be the actual size of the key. On failure, it returns -1 and sets errno. Errno values of ``EOPNOTSUPP`` and ``EOVERFLOW`` mean the same as they do for ``BLKCRYPTOIMPORTKEY``. An errno of ``EBADMSG`` indicates that the long-term wrapped key is invalid. ”h]”hý)�”}”(hX ``BLKCRYPTOPREPAREKEY`` converts a key from long-term wrapped form to ephemerally-wrapped form. It takes in a pointer to a ``struct blk_crypto_prepare_key_arg``. The caller must set ``lt_key_ptr`` and ``lt_key_size`` to the pointer and size (in bytes) of the long-term wrapped key blob to convert. On success, ``BLKCRYPTOPREPAREKEY`` returns 0 and writes the resulting ephemerally-wrapped key blob to the buffer pointed to by ``eph_key_ptr``, which is of maximum size ``eph_key_size``. It also updates ``eph_key_size`` to be the actual size of the key. On failure, it returns -1 and sets errno. Errno values of ``EOPNOTSUPP`` and ``EOVERFLOW`` mean the same as they do for ``BLKCRYPTOIMPORTKEY``. An errno of ``EBADMSG`` indicates that the long-term wrapped key is invalid.”h]”(j)�”}”(hŒ``BLKCRYPTOPREPAREKEY``”h]”hŒBLKCRYPTOPREPAREKEY”…”�”}”(hj˜ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒe converts a key from long-term wrapped form to ephemerally-wrapped form. It takes in a pointer to a ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ%``struct blk_crypto_prepare_key_arg``”h]”hŒ!struct blk_crypto_prepare_key_arg”…”�”}”(hjª h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ. The caller must set ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``lt_key_ptr``”h]”hŒ lt_key_ptr”…”�”}”(hj¼ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ and ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``lt_key_size``”h]”hŒ lt_key_size”…”�”}”(hjÎ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ_ to the pointer and size (in bytes) of the long-term wrapped key blob to convert. On success, ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOPREPAREKEY``”h]”hŒBLKCRYPTOPREPAREKEY”…”�”}”(hjà h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ] returns 0 and writes the resulting ephemerally-wrapped key blob to the buffer pointed to by ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``eph_key_ptr``”h]”hŒ eph_key_ptr”…”�”}”(hjò h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ, which is of maximum size ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``eph_key_size``”h]”hŒ eph_key_size”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ. It also updates ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``eph_key_size``”h]”hŒ eph_key_size”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ_ to be the actual size of the key. On failure, it returns -1 and sets errno. Errno values of ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``EOPNOTSUPP``”h]”hŒ EOPNOTSUPP”…”�”}”(hj( h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ and ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ ``EOVERFLOW``”h]”hŒ EOVERFLOW”…”�”}”(hj: h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ mean the same as they do for ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOIMPORTKEY``”h]”hŒBLKCRYPTOIMPORTKEY”…”�”}”(hjL h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ. An errno of ”…”�”}”(hj” h²hh³Nh´Nubj)�”}”(hŒ ``EBADMSG``”h]”hŒEBADMSG”…”�”}”(hj^ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj” ubhŒ5 indicates that the long-term wrapped key is invalid.”…”�”}”(hj” h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´Mÿhj� ubah}”(h]”h ]”h"]”h$]”h&]”uh1j{hj{ h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jûjüuh1jvh³hÇh´Mðhj9 h²hubhý)�”}”(hXUserspace needs to use either ``BLKCRYPTOIMPORTKEY`` or ``BLKCRYPTOGENERATEKEY`` once to create a key, and then ``BLKCRYPTOPREPAREKEY`` each time the key is unlocked and added to the kernel. Note that these ioctls have no relevance for raw keys; they are only for hardware-wrapped keys.”h]”(hŒUserspace needs to use either ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOIMPORTKEY``”h]”hŒBLKCRYPTOIMPORTKEY”…”�”}”(hjŠ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ or ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOGENERATEKEY``”h]”hŒBLKCRYPTOGENERATEKEY”…”�”}”(hjœ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ once to create a key, and then ”…”�”}”(hj‚ h²hh³Nh´Nubj)�”}”(hŒ``BLKCRYPTOPREPAREKEY``”h]”hŒBLKCRYPTOPREPAREKEY”…”�”}”(hj® h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚ ubhŒ˜ each time the key is unlocked and added to the kernel. Note that these ioctls have no relevance for raw keys; they are only for hardware-wrapped keys.”…”�”}”(hj‚ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M hj9 h²hubeh}”(h]”Œkernel-support”ah ]”h"]”Œkernel support”ah$]”h&]”uh1hÖhjŠh²hh³hÇh´MÏubh×)�”}”(hhh]”(hÜ)�”}”(hŒ Testability”h]”hŒ Testability”…”�”}”(hjÑ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÛhjÎ h²hh³hÇh´Mubhý)�”}”(hXSBoth the hardware KDF and the inline encryption itself are well-defined algorithms that don't depend on any secrets other than the unwrapped key. Therefore, if the unwrapped key is known to software, these algorithms can be reproduced in software in order to verify the ciphertext that is written to disk by the inline encryption hardware.”h]”hXUBoth the hardware KDF and the inline encryption itself are well-defined algorithms that don’t depend on any secrets other than the unwrapped key. Therefore, if the unwrapped key is known to software, these algorithms can be reproduced in software in order to verify the ciphertext that is written to disk by the inline encryption hardware.”…”�”}”(hjß h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MhjÎ h²hubhý)�”}”(hXÉHowever, the unwrapped key will only be known to software for testing if the "import" functionality is used. Proper testing is not possible in the "generate" case where the hardware generates the key itself. The correct operation of the "generate" mode thus relies on the security and correctness of the hardware RNG and its use to generate the key, as well as the testing of the "import" mode as that should cover all parts other than the key generation.”h]”hXÙHowever, the unwrapped key will only be known to software for testing if the “importâ€� functionality is used. Proper testing is not possible in the “generateâ€� case where the hardware generates the key itself. The correct operation of the “generateâ€� mode thus relies on the security and correctness of the hardware RNG and its use to generate the key, as well as the testing of the “importâ€� mode as that should cover all parts other than the key generation.”…”�”}”(hjí h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´MhjÎ h²hubhý)�”}”(hX"For an example of a test that verifies the ciphertext written to disk in the "import" mode, see the fscrypt hardware-wrapped key tests in xfstests, or `Android's vts_kernel_encryption_test `_.”h]”(hŒ›For an example of a test that verifies the ciphertext written to disk in the “importâ€� mode, see the fscrypt hardware-wrapped key tests in xfstests, or ”…”�”}”(hjû h²hh³Nh´NubhŒ reference”“”)�”}”(hŒŠ`Android's vts_kernel_encryption_test `_”h]”hŒ&Android’s vts_kernel_encryption_test”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œname”Œ$Android's vts_kernel_encryption_test”Œrefuri”Œ`https://android.googlesource.com/platform/test/vts-testcase/kernel/+/refs/heads/main/encryption/”uh1jhjû ubhÉ)�”}”(hŒc ”h]”h}”(h]”Œ$android-s-vts-kernel-encryption-test”ah ]”h"]”Œ$android's vts_kernel_encryption_test”ah$]”h&]”Œrefuri”juh1hÈŒ referenced”Khjû ubhŒ.”…”�”}”(hjû h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hüh³hÇh´M hjÎ h²hubeh}”(h]”Œ testability”ah ]”h"]”Œ testability”ah$]”h&]”uh1hÖhjŠh²hh³hÇh´Mubeh}”(h]”(j�Œid2”eh ]”h"]”(Œhardware-wrapped keys”Œhardware_wrapped_keys”eh$]”h&]”uh1hÖhhØh²hh³hÇh´M1Œexpect_referenced_by_name”}”j=jwsŒexpect_referenced_by_id”}”j�jwsubeh}”(h]”(hÕŒid1”eh ]”h"]”(Œinline encryption”Œinline_encryption”eh$]”h&]”uh1hÖhhh²hh³hÇh´Kj@}”jJhÊsjB}”hÕhÊsubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hÛNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jrŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”(hÕ]”hÊaj�]”jwauŒnameids”}”(jJhÕjIjFj;j8jbj_jjÿj jjðjíj©j¦j jjGjDj‡j„j=j�j<j9j`j]j4 j1 j6 j3 jË jÈ j4j1j juŒ nametypes”}”(jJˆjI‰j;‰jb‰j‰j ‰jð‰j©‰j ‰jG‰j‡‰j=ˆj<‰j`‰j4 ‰j6 ‰jË ‰j4‰j ˆuh}”(hÕhØjFhØj8hëj_j>jÿjejjjíjj¦jójj¬jDj#j„jJj�jŠj9jŠj]j›j1 jcj3 j7 jÈ j9 j1jÎ jjuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”j€Ks…”R”Œparse_messages”]”Œtransform_messages”]”(hŒsystem_message”“”)�”}”(hhh]”hý)�”}”(hhh]”hŒ7Hyperlink target "inline-encryption" is not referenced.”…”�”}”hjÝsbah}”(h]”h ]”h"]”h$]”h&]”uh1hühjÚubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”ŒINFO”Œsource”hÇŒline”Kuh1jØubjÙ)�”}”(hhh]”hý)�”}”(hhh]”hŒ;Hyperlink target "hardware-wrapped-keys" is not referenced.”…”�”}”hjøsbah}”(h]”h ]”h"]”h$]”h&]”uh1hühjõubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”jòŒsource”hÇŒline”M.uh1jØubeŒ transformer”NŒ include_log”]”Œ decoration”Nh²hub.