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

Linlin Zhang
2026-02-10T08:32:16Z

Inline encryption on virtio block can only be supported when
the new feature bit VIRTIO_BLK_F_ICE is negotiated.

Extend struct virtio_blk_config and struct virtio_blk_req,
so that crypto capabilities can be got in the frontend and
encryption metadata can be sent to the backend, together with
each I/O transaction.

About the inline encryption on UFS or eMMC storage, please
refer to the Linux inline encryption documentation:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/block/inline-encryption.rst

Fixes: https://github.com/oasis-tcs/virtio-spec/issues/238
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: linlzhan <quic_linlzhan@quicinc.com>
Signed-off-by: Linlin Zhang <linlin.zhang@oss.qualcomm.com>
---
device-types/blk/description.tex | 110 ++++++++++++++++++++++++++++++-
1 file changed, 108 insertions(+), 2 deletions(-)

diff --git a/device-types/blk/description.tex b/device-types/blk/description.tex
index 2712ada..60f46af 100644
--- a/device-types/blk/description.tex
+++ b/device-types/blk/description.tex
@@ -66,6 +66,11 @@ \subsection{Feature bits}\label{sec:Device Types / Block Device / Feature bits}
(ZNS). For brevity, these standard documents are referred as "ZBD standards"
from this point on in the text.

+\item[VIRTIO_BLK_F_ICE(22)] Inline Crypto Extensions are supported. Only when this
+ feature bit is negotiated, the device need expose crypto characteristics in
+ configuration space and the driver need provide an extended request header
+ containing a crypto payload for block I/O.
+
\end{description}

\subsubsection{Legacy Interface: Feature bits}\label{sec:Device Types / Block Device / Feature bits / Legacy Interface: Feature bits}
@@ -128,6 +133,10 @@ \subsection{Device configuration layout}\label{sec:Device Types / Block Device /
u8 model;
u8 unused2[3];
} zoned;
+ struct virtio_blk_crypto_characteristics {
+ __virtio16 slot_info;
+ __virtio16 reserved;
+ } crypto;
};
\end{lstlisting}

@@ -215,6 +224,18 @@ \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_ICE feature is negotiated, then in
+\field{virtio_blk_crypto_characteristics},
+\begin{itemize}
+\item \field{slot_info} value packs two 8-bits values to reduce the number of
+ Configuration Space reads.
+ \begin{itemize}
+ \item Bits~\[15:8] (\emph{max\_slots}): the maximum number of supported
+ crypto key slots.
+ \item Bits~\[7:0] (\emph{slot\_offset}): an offset applied to slot numbering.
+ \end{itemize}
+\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
@@ -278,6 +299,10 @@ \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_ICE feature is negotiated, the fields in
+ \field{crypto} can be read by the driver to determine the inline crypto
+ characteristics of the device. All \field{crypto} fields are read-only.
+
\end{enumerate}

\drivernormative{\subsubsection}{Device Initialization}{Device Types / Block Device / Device Initialization}
@@ -317,6 +342,9 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic
driver SHOULD ignore all other fields in \field{zoned}.
\end{itemize}

+If the VIRTIO_BLK_F_ICE feature is negotiated, then the driver MUST validate
+ the max_slots in \field{slot_info} before the slot usage.
+
\devicenormative{\subsubsection}{Device Initialization}{Device Types / Block Device / Device Initialization}

Devices SHOULD always offer VIRTIO_BLK_F_FLUSH, and MUST offer it
@@ -402,6 +430,13 @@ \subsection{Device Initialization}\label{sec:Device Types / Block Device / Devic
\item the device MUST initialize padding bytes \field{unused2} to 0.
\end{itemize}

+If the VIRTIO_BLK_F_ICE feature is negotiated, then the fields in \field{crypto}
+struct in the configuration space MUST be set by the device.
+\begin{itemize}
+\item the \field{slot_info} field of \field{crypto} MUST be set by the device to a
+ max_slots in the higher 8 bits and slot_offset in the lower 8 bits.
+\end{itemize}
+
\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
@@ -436,6 +471,13 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope
le32 type;
le32 reserved;
le64 sector;
+ struct virtio_blk_crypto_payload {
+ u8 slot;
+ u8 activate;
+ le16 reserved1;
+ le32 reserved2;
+ le64 data_unit_num;
+ } payload;
u8 data[];
u8 status;
};
@@ -445,8 +487,9 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope
(VIRTIO_BLK_T_OUT), a discard (VIRTIO_BLK_T_DISCARD), a write zeroes
(VIRTIO_BLK_T_WRITE_ZEROES), a flush (VIRTIO_BLK_T_FLUSH), a get device ID
string command (VIRTIO_BLK_T_GET_ID), a secure erase
-(VIRTIO_BLK_T_SECURE_ERASE), or a get device lifetime command
-(VIRTIO_BLK_T_GET_LIFETIME).
+(VIRTIO_BLK_T_SECURE_ERASE), a get device lifetime command
+(VIRTIO_BLK_T_GET_LIFETIME), or a get device crypto capabilities command
+(VIRTIO_BLK_T_GET_CRYPTO_CAPABILITIES).

\begin{lstlisting}
#define VIRTIO_BLK_T_IN 0
@@ -457,12 +500,27 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope
#define VIRTIO_BLK_T_DISCARD 11
#define VIRTIO_BLK_T_WRITE_ZEROES 13
#define VIRTIO_BLK_T_SECURE_ERASE 14
+#define VIRTIO_BLK_T_GET_CRYPTO_CAPABILITIES 27
\end{lstlisting}

The \field{sector} number indicates the offset (multiplied by 512) where
the read or write is to occur. This field is unused and set to 0 for
commands other than read, write and some zone operations.

+The \field{payload} consists of the encryption information for current
+request. It is only present when the VIRTIO_BLK_F_ICE feature is negotiated and
+\field{type} is VIRTIO_BLK_T_IN, VIRTIO_BLK_T_OUT or VIRTIO_BLK_T_FLUSH.
+\begin{itemize}
+\item The \field{slot} field in \field{payload} indicates the ICE
+ (Inline Crypto Encryption) slot index where the key resides.
+
+\item The \field{activate} field in \field{payload} implies this is a
+ inline encryption request.
+
+\item The \field{data_unit_num} field in \field{payload} indicates the
+ starting block of the request.
+\end{itemize}
+
VIRTIO_BLK_T_IN requests populate \field{data} with the contents of sectors
read from the block device (in multiples of 512 bytes). VIRTIO_BLK_T_OUT
requests write the contents of \field{data} to the block device (in multiples
@@ -530,6 +588,47 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope
The \field{device_lifetime_est_typ_b} refers to wear of MLC cells and is provided
with the same semantics as \field{device_lifetime_est_typ_a}.

+VIRTIO_BLK_T_GET_CRYPTO_CAPABILITIES requests fetch the storage hardware crypto
+capabilities into \field{data}. And the \field{data} is of the form
+
+\begin{lstlisting}
+struct virtio_blk_crypto_caps {
+ u8 size;
+ le32 crypto_capabilities[];
+};
+\end{lstlisting}
+
+The \field{size} specifies the size of array \field{crypto_capabilities}.
+The \field{crypto_capabilities} indicates the crypto capabilities supported by the
+hardware storage for inline encryption.
+
+A crypto capability packs four 8-bits values:
+\begin{itemize}
+ \item Bits~\[31:24]: crypto algorithm identifiers.
+ The device supports reporting and negotiating cryptographic algorithms
+ using the following algorithm identifiers:
+ \begin{lstlisting}
+ CRYPTO_ALG_AES_XTS = 0x0
+ CRYPTO_ALG_BITLOCKER_AES_CBC = 0x1
+ CRYPTO_ALG_AES_ECB = 0x2
+ CRYPTO_ALG_ESSIV_AES_CBC = 0x3
+ \end{lstlisting}
+ These identifiers abstract the underlying hardware crypto implementation
+ and does not assume any operating‑system‑specific data structures or
+ constants.
+ \item Bits~\[23:16]: mask of data unit size. When bit j in this field
+ (j=7......0) is set, a data unit size of 512*2^j bytes is selected.
+ \item Bits~\[15:8]: crypto key size identifiers.
+ \begin{lstlisting}
+ CRYPTO_KEY_SIZE_INVALID = 0x0
+ CRYPTO_KEY_SIZE_128_BITS = 0x1
+ CRYPTO_KEY_SIZE_192_BITS = 0x2
+ CRYPTO_KEY_SIZE_256_BITS = 0x3
+ CRYPTO_KEY_SIZE_512_BITS = 0x4
+ \end{lstlisting}
+ \item Bits~\[7:0]: unused.
+\end{itemize}
+
The final \field{status} byte is written by the device: either
VIRTIO_BLK_S_OK for success, VIRTIO_BLK_S_IOERR for device or driver
error or VIRTIO_BLK_S_UNSUPP for a request unsupported by device:
@@ -912,6 +1011,13 @@ \subsection{Device Operation}\label{sec:Device Types / Block Device / Device Ope
successfully, failed, or were processed by the device at all if the request
failed with VIRTIO_BLK_S_IOERR.

+The length of \field{data} MUST be a multiple of 4 bytes plus 1 for
+VIRTIO_BLK_T_GET_CRYPTO_CAPABILITIES requests.
+
+A driver MUST set \field{activate} to 1 for VIRTIO_BLK_T_IN,VIRTIO_BLK_T_OUT,
+ and VIRTIO_BLK_T_FLUSH requests that require inline encryption. For other
+ request types or when inline encryption is not required, it is set to 0.
+
The following requirements only apply if the VIRTIO_BLK_F_ZONED feature is
negotiated.

--
2.34.1