On Fri, Aug 14, 2026 at 07:23:01AM -0700, Linlin Zhang wrote: > From: linlzhan > > Add VIRTIO_BLK_F_IE to advertise inline encryption support. > > When the feature is negotiated, the device reports inline encryption > characteristics through virtio_blk_enc_characteristics. Add > VIRTIO_BLK_T_GET_CRYPTO_MODES, VIRTIO_BLK_T_CRYPTO_IN, and > VIRTIO_BLK_T_CRYPTO_OUT so that the driver can discover supported > crypto modes and submit inline-encrypted I/O requests. > > Crypto I/O requests carry a virtual key slot index, data unit size, > and initial Data Unit Number (DUN). The device maps the virtual key > slot to a physical key slot in the storage backend and uses these > parameters for inline encryption or decryption. > > Key provisioning is performed through an out-of-band mechanism and is > outside the scope of this device type. > > For background on inline encryption in UFS and eMMC storage, see: > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/block/inline-encryption.rst > > Change-Id: I83c52456bc0c9dd37f39ff46e6bfe73a715138ca > Signed-off-by: linlzhan > Fixes: https://github.com/oasis-tcs/virtio-spec/issues/238 > --- > device-types/blk/description.tex | 297 ++++++++++++++++++++++++++++++- > 1 file changed, 291 insertions(+), 6 deletions(-) Hi, I will review this on Wednesday, August 19th. In the meantime, is there a changelog from your previous patch series? Stefan > > diff --git a/device-types/blk/description.tex b/device-types/blk/description.tex > index 3b3a4e7..f8a544b 100644 > --- a/device-types/blk/description.tex > +++ b/device-types/blk/description.tex > @@ -71,7 +71,16 @@ \subsection{Feature bits}\label{sec:Device Types / Block Device / Feature bits} > > \item[VIRTIO_BLK_F_REQ_FLAGS_OUT_FUA (19)] Device supports the > VIRTIO_BLK_REQ_FLAG_OUT_FUA flag in the \field{flags} bitfield of the > - \field{virtio_blk_req} structure for VIRTIO_BLK_T_OUT requests. > + request for VIRTIO_BLK_T_OUT and VIRTIO_BLK_T_CRYPTO_OUT requests. > + > +\item[VIRTIO_BLK_F_IE (22)] Only when the storage backend supports inline > + encryption and this feature bit is negotiated, the data read from or > + written to the device can be decrypted from or encrypted to the storage > + via inline crypto engine. Keys are provisioned into key slots of the > + inline crypto engine through a mechanism outside the scope of this device > + type, and requests identify, by key slot index, which provisioned key to > + use. The number of key slots, the maximum DUN size and the supported key > + types are reported in \field{enc_characteristics}. > > \end{description} > > @@ -135,6 +144,12 @@ \subsection{Device configuration layout}\label{sec:Device Types / Block Device / > u8 model; > u8 unused2[3]; > } zoned; > + struct virtio_blk_enc_characteristics { > + le16 max_slots; > + u8 max_dun_bytes; > + u8 key_types; > + le32 unused3; > + } enc_characteristics; > }; > \end{lstlisting} > > @@ -222,6 +237,39 @@ \subsection{Device configuration layout}\label{sec:Device Types / Block Device / > terminated by the device with a "zone resources exceeded" error as defined for > specific commands later. > > +If the VIRTIO_BLK_F_IE feature is negotiated, then in > +\field{virtio_blk_enc_characteristics}, > +\begin{itemize} > +\item \field{max_slots} is the number of key slots allocated to the Guest VM. > + It MUST not exceed the number of key slots supported by the inline crypto > + engine of the device backend storage. Key slots are indexed from 0 to > + \field{max_slots} - 1. > + > +\item \field{max_dun_bytes} is the maximum number of bytes of the Data Unit > + Number (DUN) that the device supports for any of its supported crypto > + modes. For example, known inline crypto engines report a > + \field{max_dun_bytes} of 4 (JEDEC eMMC Command Queue Host Controller > + Interface, CQHCI) or 8 (JEDEC UFS Host Controller Interface, UFSHCI); > + a device backed by different inline crypto engine hardware MAY report > + a different value, subject to the constraints in > + \ref{devicenormative:Device Types / Block Device / Device Initialization}. > + > +\item \field{key_types} is a bitmask of the key types the device supports, > + using the following values: > + \begin{lstlisting} > +#define VIRTIO_BLK_CRYPTO_KEY_TYPE_RAW (1 << 0) > +#define VIRTIO_BLK_CRYPTO_KEY_TYPE_HW_WRAPPED (1 << 1) > + \end{lstlisting} > + VIRTIO_BLK_CRYPTO_KEY_TYPE_RAW indicates that keys are provisioned into > + key slots in raw (plaintext) form. VIRTIO_BLK_CRYPTO_KEY_TYPE_HW_WRAPPED > + indicates that the key exists only in ephemerally-wrapped form in memory > + outside of dedicated hardware, and can only be unwrapped and provisioned > + into key slots by dedicated hardware (e.g. a hardware key manager). The > + plaintext key never exists in software-accessible memory. > + > +\item \field{unused3} is reserved for future use. > +\end{itemize} > + > \subsubsection{Legacy Interface: Device configuration layout}\label{sec:Device Types / Block Device / Device configuration layout / Legacy Interface: Device configuration layout} > When using the legacy interface, transitional devices and drivers > MUST format the fields in struct virtio_blk_config > @@ -285,6 +333,14 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic > \field{zoned} can be read by the driver to determine the zone > characteristics of the device. All \field{zoned} fields are read-only. > > +\item If the VIRTIO_BLK_F_IE feature is negotiated, the fields in > + \field{enc_characteristics} can be read by the driver to determine the > + inline encryption capabilities of the device, and a > + VIRTIO_BLK_T_GET_CRYPTO_MODES request (see > + \ref{sec:Device Types / Block Device / Device Operation}) can be sent > + to retrieve the set of supported crypto modes. All > + \field{enc_characteristics} fields are read-only. > + > \end{enumerate} > > \drivernormative{\subsubsection}{Device Initialization}{Device Types / Block Device / Device Initialization} > @@ -312,6 +368,10 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic > offered by the device with the VIRTIO_BLK_Z_HA or VIRTIO_BLK_Z_NONE zone model, > then the driver MAY negotiate these two bits independently. > > +Zoned devices do not support inline encryption. If the VIRTIO_BLK_F_ZONED > +feature is offered by the device, then the VIRTIO_BLK_F_IE feature MUST NOT > +be negotiated by the driver. > + > If the VIRTIO_BLK_F_ZONED feature is negotiated, then > \begin{itemize} > \item if the driver that can not support host-managed zoned devices > @@ -327,6 +387,12 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic > The driver MUST NOT negotiate VIRTIO_BLK_F_REQ_FLAGS_OUT_FUA without > VIRTIO_BLK_F_REQ_FLAGS. > > +Drivers MUST NOT negotiate the VIRTIO_BLK_F_IE feature if they are > +incapable of provisioning keys into the key slots of the device backend > +storage's inline crypto engine, or of conveying the key slot index, > +data unit size in bits, and Data Unit Number (DUN) per request to > +the device using the \field{virtio_blk_crypto_msg} structure. > + > \devicenormative{\subsubsection}{Device Initialization}{Device Types / Block Device / Device Initialization} > > Devices SHOULD always offer VIRTIO_BLK_F_FLUSH, and MUST offer it > @@ -341,9 +407,15 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic > If the device that is being initialized is a not a zoned device, the device > SHOULD NOT offer the VIRTIO_BLK_F_ZONED feature. > > +A zoned device MUST NOT offer the VIRTIO_BLK_F_IE feature. > + > The VIRTIO_BLK_F_ZONED feature cannot be properly negotiated without > FEATURES_OK bit. Legacy devices MUST NOT offer VIRTIO_BLK_F_ZONED feature bit. > > +The VIRTIO_BLK_F_IE feature cannot be properly negotiated without > +FEATURES_OK bit. Legacy devices MUST NOT offer the VIRTIO_BLK_F_IE feature > +bit. > + > If the VIRTIO_BLK_F_ZONED feature is not accepted by the driver, > \begin{itemize} > \item the device with the VIRTIO_BLK_Z_HA or VIRTIO_BLK_Z_NONE zone model SHOULD > @@ -415,6 +487,26 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic > The device MUST NOT acknowledge FEATURES_OK if the driver sets > VIRTIO_BLK_F_REQ_FLAGS_OUT_FUA without VIRTIO_BLK_F_REQ_FLAGS. > > +The device MUST NOT acknowledge FEATURES_OK if the driver negotiates both > +VIRTIO_BLK_F_ZONED and VIRTIO_BLK_F_IE. > + > +If the device is incapable of consuming the \field{virtio_blk_crypto_msg}, > +the device SHOULD NOT offer the VIRTIO_BLK_F_IE feature. > + > +If the VIRTIO_BLK_F_IE feature is negotiated, the device MUST set > +\field{max_slots} in \field{enc_characteristics} to a value greater than 0. > + > +If the VIRTIO_BLK_F_IE feature is negotiated, the device MUST set > +\field{key_types} in \field{enc_characteristics} to have at least one of > +VIRTIO_BLK_CRYPTO_KEY_TYPE_RAW or VIRTIO_BLK_CRYPTO_KEY_TYPE_HW_WRAPPED > +set, and MUST NOT set any bit in \field{key_types} other than > +VIRTIO_BLK_CRYPTO_KEY_TYPE_RAW and VIRTIO_BLK_CRYPTO_KEY_TYPE_HW_WRAPPED. > +The device MUST initialize padding bytes \field{unused3} to 0. > + > +The device MUST NOT set \field{max_dun_bytes} in \field{enc_characteristics} > +to 0 or to a value greater than 8, since \field{dun} of > +\field{virtio_blk_crypto_msg} is a fixed 8-byte field. > + > \subsubsection{Legacy Interface: Device Initialization}\label{sec:Device Types / Block Device / Device Initialization / Legacy Interface: Device Initialization} > > Because legacy devices do not have FEATURES_OK, transitional devices > @@ -478,8 +570,8 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope > value is the bit index in the \field{flags} bitfield): > > \begin{description} > -\item[VIRTIO_BLK_REQ_FLAG_OUT_FUA (0) for VIRTIO_BLK_T_OUT requests] Force Unit > - Access (FUA) flag. > +\item[VIRTIO_BLK_REQ_FLAG_OUT_FUA (0) for VIRTIO_BLK_T_OUT and > + VIRTIO_BLK_T_CRYPTO_OUT requests] Force Unit Access (FUA) flag. > \end{description} > > The \field{sector} number indicates the offset (multiplied by 512) where > @@ -886,6 +978,108 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope > operation by setting the VIRTIO_BLK_S_ZONE_INVALID_CMD value in > \field{status} of \field{virtio_blk_req} structure. > > +The following requirements only apply if the VIRTIO_BLK_F_IE feature is > +negotiated. > + > +In addition to the request types defined for devices without inline > +encryption support, the type of the request can be an inline-encrypted read > +(VIRTIO_BLK_T_CRYPTO_IN), an inline-encrypted write (VIRTIO_BLK_T_CRYPTO_OUT) > +or a get crypto modes command (VIRTIO_BLK_T_GET_CRYPTO_MODES). > + > +\begin{lstlisting} > +#define VIRTIO_BLK_T_CRYPTO_OUT 27 > +#define VIRTIO_BLK_T_CRYPTO_IN 28 > +#define VIRTIO_BLK_T_GET_CRYPTO_MODES 30 > +\end{lstlisting} > + > +VIRTIO_BLK_T_CRYPTO_IN and VIRTIO_BLK_T_CRYPTO_OUT requests behave the same > +as VIRTIO_BLK_T_IN and VIRTIO_BLK_T_OUT requests respectively, except that > +the data in \field{data} is decrypted (for VIRTIO_BLK_T_CRYPTO_IN) or is to > +be encrypted (for VIRTIO_BLK_T_CRYPTO_OUT) by the inline crypto engine in > +the device backend storage using the key already provisioned in the key > +slot identified by the request, combined with the request's Data Unit > +Number (DUN). For this reason, the VIRTIO_BLK_T_CRYPTO_IN and > +VIRTIO_BLK_T_CRYPTO_OUT requests have the layout that is extended to have > +the \field{crypto_msg} field to carry this information: > + > +\begin{lstlisting} > +struct virtio_blk_req_crypto { > + le32 type; > + le32 flags; > + le64 sector; > + struct virtio_blk_crypto_msg crypto_msg; > + u8 data[]; > + u8 status; > +}; > +\end{lstlisting} > + > +\field{crypto_msg} has the following structure: > + > +\begin{lstlisting} > +struct virtio_blk_crypto_msg { > + le32 slot; > + le32 data_unit_size_bits; > + le64 dun; > +}; > +\end{lstlisting} > + > +\field{slot} is the virtual key slot index, in the range from 0 to > +\field{max_slots} - 1 of \field{enc_characteristics}. The device maps this > +virtual key slot index to a physical key slot in the inline crypto engine of > +the device backend storage. > +\field{data_unit_size_bits} is $log_2$ of the data unit size in bytes, > +used for calculating DUNs for sub-requests if the request is split. > +\field{dun} is the Data Unit Number, that is, the initial value that the > +inline crypto engine increments by one for each successive data unit of > +the size specified by \field{data_unit_size_bits}, while encrypting or > +decrypting the data of the request. > + > +VIRTIO_BLK_T_GET_CRYPTO_MODES is a read request that returns the data unit > +sizes with which each of the device's crypto modes can be used. The > +response consists of a header followed by zero or more \field{le32} > +bitmask elements, indexed by crypto mode number: > + > +\begin{lstlisting} > +struct virtio_blk_crypto_modes { > + le32 nr_modes; > + u8 reserved[4]; > + le32 modes[]; > +}; > +\end{lstlisting} > + > +The device sets \field{nr_modes} in the response header to the number of > +fully transferred \field{modes} elements in the data buffer. \field{modes[N]}, > +for crypto mode number N, is a bitmask indicating the data unit sizes with > +which crypto mode N can be used by the device: the i'th bit of > +\field{modes[N]} is set if crypto mode N can be used with a data unit size > +of $(1 << i)$ bytes. A value of 0 for a \field{modes} element indicates > +that the device does not support the corresponding crypto mode at all. > +Crypto mode number 0 is reserved; \field{modes[0]} is always set to 0 by > +the device. > + > +Crypto mode numbers are assigned by this specification, independently of > +any operating system's internal representation of crypto algorithms, so > +that support for additional crypto modes can be added in future revisions > +of this specification without changing the meaning of previously assigned > +numbers: > + > +\begin{lstlisting} > +#define VIRTIO_BLK_CRYPTO_MODE_AES_256_XTS 1 > +#define VIRTIO_BLK_CRYPTO_MODE_AES_128_CBC_ESSIV 2 > +#define VIRTIO_BLK_CRYPTO_MODE_ADIANTUM 3 > +#define VIRTIO_BLK_CRYPTO_MODE_SM4_XTS 4 > +\end{lstlisting} > + > +A driver or device implementation MAY support only a subset of these > +crypto modes. Crypto mode numbers already assigned by this or an earlier > +version of this specification are never reused for a different crypto > +mode; additional crypto modes are assigned new numbers, greater than the > +highest number defined by the version of this specification the > +implementation supports. > + > +VIRTIO_BLK_T_CRYPTO_IN and VIRTIO_BLK_T_GET_CRYPTO_MODES requests are reads, > +and VIRTIO_BLK_T_CRYPTO_OUT requests are writes. > + > \drivernormative{\subsubsection}{Device Operation}{Device Types / Block Device / Device Operation} > > The driver SHOULD check if the content of the \field{capacity} field has > @@ -904,8 +1098,8 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope > A driver MUST set \field{sector} to 0 for a VIRTIO_BLK_T_FLUSH request. > A driver SHOULD NOT include any data in a VIRTIO_BLK_T_FLUSH request. > > -The length of \field{data} MUST be a multiple of 512 bytes for VIRTIO_BLK_T_IN > -and VIRTIO_BLK_T_OUT requests. > +The length of \field{data} MUST be a multiple of 512 bytes for VIRTIO_BLK_T_IN, > +VIRTIO_BLK_T_OUT, VIRTIO_BLK_T_CRYPTO_IN and VIRTIO_BLK_T_CRYPTO_OUT requests. > > The length of \field{data} MUST be a multiple of the size of struct > virtio_blk_discard_write_zeroes for VIRTIO_BLK_T_DISCARD, > @@ -984,6 +1178,42 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope > > \end{enumerate} > > +The following requirements only apply if the VIRTIO_BLK_F_IE feature is > +negotiated. > + > +A driver MUST NOT submit a VIRTIO_BLK_T_CRYPTO_IN or VIRTIO_BLK_T_CRYPTO_OUT > +request with a \field{slot} value that is not less than \field{max_slots} of > +\field{enc_characteristics}, or that identifies a key slot into which no key > +has been provisioned. > + > +A driver MUST set \field{data_unit_size_bits} of a VIRTIO_BLK_T_CRYPTO_IN or > +VIRTIO_BLK_T_CRYPTO_OUT request's \field{crypto_msg} to $log_2$ of the data > +unit size in bytes associated with the key provisioned in the virtual key > +slot identified by \field{slot}. Since data unit sizes are reported by > +VIRTIO_BLK_T_GET_CRYPTO_MODES as a bitmask of \field{le32} elements, a > +driver MUST NOT set \field{data_unit_size_bits} to a value greater than 31. > + > +A driver MUST NOT submit a VIRTIO_BLK_T_CRYPTO_IN or VIRTIO_BLK_T_CRYPTO_OUT > +request with a zero length \field{data}. > + > +A driver MUST NOT submit a VIRTIO_BLK_T_CRYPTO_IN or VIRTIO_BLK_T_CRYPTO_OUT > +request unless \field{sector}, multiplied by 512, and the length of > +\field{data}, are both a multiple of $(1 << \field{data_unit_size_bits})$ > +bytes. > + > +A driver MUST NOT submit a VIRTIO_BLK_T_CRYPTO_IN or VIRTIO_BLK_T_CRYPTO_OUT > +request if \field{dun} + $N$ - 1 is not representable in > +\field{max_dun_bytes} bytes, where $N$ is the number of data units of > +$2^{\field{data_unit_size_bits}}$ bytes in \field{data}. > + > +A driver MUST treat any crypto mode number that is not less than > +\field{nr_modes} of a VIRTIO_BLK_T_GET_CRYPTO_MODES response as unsupported > +by the device. > + > +A driver MUST provide a \field{data} buffer of at least > +sizeof(struct virtio_blk_crypto_modes) (8) bytes for a > +VIRTIO_BLK_T_GET_CRYPTO_MODES request. > + > \devicenormative{\subsubsection}{Device Operation}{Device Types / Block Device / Device Operation} > > The device MAY change the content of the \field{capacity} field during > @@ -1030,7 +1260,8 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope > > \item\label{item:flush3} the VIRTIO_BLK_F_REQ_FLAGS_OUT_FUA feature was > negotiated and the VIRTIO_BLK_REQ_FLAG_OUT_FUA bit in \field{flags} was set in > - the write request (regardless of whether the VIRTIO_BLK_F_FLUSH or > + the write request (VIRTIO_BLK_T_OUT or VIRTIO_BLK_T_CRYPTO_OUT, regardless of > + whether the VIRTIO_BLK_F_FLUSH or > VIRTIO_BLK_F_CONFIG_WCE features were negotiated, and regardless of the > current cache mode as expressed by the value of the \field{writeback} field in > configuration space). > @@ -1225,6 +1456,60 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope > handles VIRTIO_BLK_T_ZONE_RESET request for the zone range specified in the > VIRTIO_BLK_T_SECURE_ERASE request. > > +The following requirements only apply if the VIRTIO_BLK_F_IE feature is > +negotiated. > + > +If a VIRTIO_BLK_T_CRYPTO_IN or VIRTIO_BLK_T_CRYPTO_OUT request: > +\begin{itemize} > +\item specifies a \field{slot} value that is not less than \field{max_slots}, > + or that identifies a key slot into which no key has been provisioned, > + > +\item specifies a \field{data_unit_size_bits} value greater than 31, or > + that does not match $log_2$ of the data unit size in bytes associated > + with the key provisioned in the virtual key slot identified by the > + \field{slot}, > + > +\item specifies a zero length \field{data}, > + > +\item specifies a \field{sector}, multiplied by 512, or a length of > + \field{data}, that is not a multiple of $(1 << \field{data_unit_size_bits})$ > + bytes, or > + > +\item specifies a \field{dun} such that \field{dun} + $N$ - 1 is not > + representable in \field{max_dun_bytes} bytes, where $N$ is the number > + of data units of $2^{\field{data_unit_size_bits}}$ bytes in > + \field{data}, > +\end{itemize} > +then the device MUST set the \field{status} byte to VIRTIO_BLK_S_UNSUPP and > +MUST NOT read or write any data. > + > +If a VIRTIO_BLK_T_GET_CRYPTO_MODES request's \field{data} buffer is smaller > +than sizeof(struct virtio_blk_crypto_modes) (8) bytes, the device MUST set > +the \field{status} byte to VIRTIO_BLK_S_UNSUPP and MUST NOT write any data. > + > +If the driver's \field{data} buffer in a VIRTIO_BLK_T_GET_CRYPTO_MODES > +request is not large enough to hold \field{modes} elements up to the > +highest crypto mode number the device supports, the device MUST set > +\field{nr_modes} to the number of complete \field{modes} elements that fit > +in the buffer, and MUST NOT write a partial element. > + > +The device MUST initialize padding bytes \field{reserved} of a > +VIRTIO_BLK_T_GET_CRYPTO_MODES response to 0. > + > +For a VIRTIO_BLK_T_CRYPTO_IN or VIRTIO_BLK_T_CRYPTO_OUT request, the device > +MUST use the key provisioned in the virtual key slot identified by > +\field{slot} of the request's \field{crypto_msg}, combined with \field{dun}, > +to decrypt the data read from, or encrypt the data written to, the device > +backend storage. If the device backend storage splits the request into > +sub-requests, each sub-request MUST begin at a byte offset, from the start > +of \field{data}, that is a multiple of $(1 << \field{data_unit_size_bits})$ > +bytes, MUST have a length that is a multiple of > +$(1 << \field{data_unit_size_bits})$ bytes, and MUST use, in place of > +\field{dun}, the Data Unit Number > +$\field{dun} + (\mathit{byte\_offset} / (1 << \field{data_unit_size_bits}))$, > +where $\mathit{byte\_offset}$ is that sub-request's starting byte offset > +from the start of \field{data}. > + > \subsubsection{Legacy Interface: Device Operation}\label{sec:Device Types / Block Device / Device Operation / Legacy Interface: Device Operation} > When using the legacy interface, transitional devices and drivers > MUST format the fields in struct virtio_blk_req > -- > 2.34.1 >