[PATCH v2] virtio-blk: Add inline encryption support

Linlin Zhang <[email protected]>
Newsgroups dev.linux.lists.virtio-dev
Message-ID <[email protected]>
From: linlzhan <[email protected]>

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

Signed-off-by: linlzhan <[email protected]>
Fixes: https://github.com/oasis-tcs/virtio-spec/issues/238

changes in v2:
 - Revmove virtualization-specific terminology
 - Move MUST sentence to the device/driver normative section
 - Add explicit rejection for CRYPTO request if IE feature bit
   isn't negociated
 - Modify the support list of crypto modes and the definition of
   the size of the crypto modes buffer
---
 device-types/blk/description.tex              | 312 +++++++++++++-
 ...ec_update_for_fbe_virtualization_0814.diff | 402 ++++++++++++++++++
 2 files changed, 707 insertions(+), 7 deletions(-)
 create mode 100644 new_virtio_spec_update_for_fbe_virtualization_0814.diff

diff --git a/device-types/blk/description.tex b/device-types/blk/description.tex
index 3b3a4e7..0488458 100644
--- a/device-types/blk/description.tex
+++ b/device-types/blk/description.tex
@@ -70,8 +70,19 @@ \subsection{Feature bits}\label{sec:Device Types / Block Device / Feature bits}
     bitfield in the \field{virtio_blk_req} structure.
 
 \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.
+    VIRTIO_BLK_REQ_FLAG_OUT_FUA flag in the \field{flags} bitfield in the
+    \field{virtio_blk_req} structure for VIRTIO_BLK_T_OUT and
+    VIRTIO_BLK_T_CRYPTO_OUT requests.
+
+\item[VIRTIO_BLK_F_INLINE_ENCRYPTION (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 an 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 size of
+    the Data Unit Number (DUN) and the supported key types are reported
+    in \field{enc_characteristics}.
 
 \end{description}
 
@@ -135,6 +146,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 +239,34 @@ \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_INLINE_ENCRYPTION feature is negotiated, then in
+\field{virtio_blk_enc_characteristics},
+\begin{itemize}
+\item \field{max_slots} is the number of available key slots. 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).
+
+\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 +330,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_INLINE_ENCRYPTION 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 +365,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_INLINE_ENCRYPTION
+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 +384,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_INLINE_ENCRYPTION 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 +404,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_INLINE_ENCRYPTION 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_INLINE_ENCRYPTION feature cannot be properly negotiated without
+FEATURES_OK bit. Legacy devices MUST NOT offer the VIRTIO_BLK_F_INLINE_ENCRYPTION 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 +484,31 @@ \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_INLINE_ENCRYPTION.
+
+If the device is incapable of consuming the \field{virtio_blk_crypto_msg},
+the device SHOULD NOT offer the VIRTIO_BLK_F_INLINE_ENCRYPTION feature.
+
+If the VIRTIO_BLK_F_INLINE_ENCRYPTION feature is negotiated, the device
+MUST set \field{max_slots} in \field{enc_characteristics} to a value
+greater than 0 and less than or equal to the number of key slots supported
+by the inline crypto engine of the backend storage device.
+
+If the VIRTIO_BLK_F_INLINE_ENCRYPTION 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. The value reported by
+\field{max_dun_bytes} MAY vary depending on the capabilities of the underlying
+inline crypto engine.
+
 \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 +572,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 +980,114 @@ \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_INLINE_ENCRYPTION 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. It
+corresponds to the data unit size programmed into the keyslot configuration
+registers for the associated key during keyslot programming.
+\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 crypto modes specified by this specification.
+The response consists of zero or more \field{le32} bitmask elements,
+indexed by crypto mode number:
+
+\begin{lstlisting}
+struct virtio_blk_crypto_modes {
+        le32   modes[];
+};
+\end{lstlisting}
+
+\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, including any crypto mode number the device does not
+recognize. 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
+\end{lstlisting}
+
+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.
+
+Because crypto mode numbers, and the version of this specification each
+crypto mode was assigned in, are fixed by this specification rather than
+negotiated between the driver and the device, both sides need only refer
+to this specification to agree on their meaning: the driver sizes its
+\field{data} buffer to cover every crypto mode number defined by the
+version of this specification it implements, and the device fills in
+\field{modes[N]}, for each such N, directly according to whether and how
+it supports the crypto mode assigned to N by this specification. Neither
+side needs any additional mapping, renumbering, or out-of-band agreement
+for this.
+
+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 +1106,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 +1186,45 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope
 
 \end{enumerate}
 
+The following requirements only apply if the VIRTIO_BLK_F_INLINE_ENCRYPTION
+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 greater than \field{max_slots} - 1
+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 for which its \field{data}
+buffer does not contain a corresponding \field{modes} element as
+unsupported by the device.
+
+A driver MUST provide a \field{data} buffer large enough to hold a
+\field{modes} element for every crypto mode number defined by the
+version of this specification the driver implements: that is, a buffer
+of at least $(M + 1) \times 4$ bytes, where $M$ is the highest crypto
+mode number defined by that version of this specification (the $+1$
+accounts for the reserved crypto mode number 0).
+
 \devicenormative{\subsubsection}{Device Operation}{Device Types / Block Device / Device Operation}
 
 The device MAY change the content of the \field{capacity} field during
@@ -1030,7 +1271,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 +1467,62 @@ \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.
 
+If the VIRTIO_BLK_F_INLINE_ENCRYPTION feature is not negotiated, the device
+MUST reject VIRTIO_BLK_T_CRYPTO_IN, VIRTIO_BLK_T_CRYPTO_OUT and
+VIRTIO_BLK_T_GET_CRYPTO_MODES requests with VIRTIO_BLK_S_UNSUPP status.
+
+The following requirements only apply if the VIRTIO_BLK_F_INLINE_ENCRYPTION 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 cannot
+hold at least one complete \field{modes} element (4 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 write
+as many complete \field{modes} elements as fit in the buffer, and MUST
+NOT write a partial element.
+
+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
diff --git a/new_virtio_spec_update_for_fbe_virtualization_0814.diff b/new_virtio_spec_update_for_fbe_virtualization_0814.diff
new file mode 100644
index 0000000..fb2147f
--- /dev/null
+++ b/new_virtio_spec_update_for_fbe_virtualization_0814.diff
@@ -0,0 +1,402 @@
+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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.