qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [virtio-dev] [RFC v2] virtio-crypto specification


From: Stefan Hajnoczi
Subject: Re: [Qemu-devel] [virtio-dev] [RFC v2] virtio-crypto specification
Date: Mon, 11 Apr 2016 10:43:00 +0100
User-agent: Mutt/1.5.24 (2015-08-30)

On Tue, Apr 05, 2016 at 09:14:09AM +0000, Gonglei (Arei) wrote:
>                  Virtio-crypto device Spec
> 
> 1     Crypto Device
> The virtio crypto device is a virtual crypto device (ie. hardware crypto 
> accelerator card). The encryption and decryption requests of are placed in 
> the data queue, and handled by the real hardware crypto accelerators finally. 
> A second queue is the control queue, which is used to create or destroy 
> session for symmetric algorithms, and to control some advanced features.
> 1.1   Device ID
> 65535 (experimental)
> 
> 1.2   Virtqueues
> 0  dataq
>
> N-1  dataq
> N  controlq
> 
> N=1 if VIRTIO_CRYPTO_F_MQ is not negotiated, otherwise N is set by 
> max_virtqueues.

Feature bits are useful for adding new functionality in a backwards
compatible way.  Since this is a new device specification, there's no
need to "extend" the device with VIRTIO_CRYPTO_F_MQ.

VIRTIO_CRYPTO_F_MQ can be eliminated to make the specification and
implementation simpler.  Just set the max_virtqueue configuration field
to 1 if the device only supports a single data virtqueue.


Questions about multiqueue:

1. Can the driver use the same session ID across multiple queues?  At
   the same time?

2. On multiqueue devices all vcpus still use a single controlq to create
   a session.  I imagine this defeats the purpose of multiqueue when the
   application creates sessions frequently.  Did you implement and
   benchmark multiqueue?

3. Did you consider inline session create/close?  In other words, let
   dataq buffers start with either virtio_crypto_sym_crypt_op or:

     struct virtio_crypto_sym_crypt_op_create {
         /* Start with an embedded op struct where session_id is 0 */
         struct virtio_crypto_sym_crypt_op op;

         virtio_crypto_sym_cipher_t cipher_setup_data;
         virtio_crypto_sym_hash_t hash_setup_data;
         virtio_crypto_sym_alg_chain_order_t alg_chain_order;
         u8 verify_digest;
     };

   When the device sees an op with session_id 0 it reads the additional
   virtio_crypto_sym_crypt_op_create fields and creates the session
   before processing the rest of virtio_crypto_sym_crypt_op.

   This way no extra round-trip is required for session creation.  A
   similar approach is possible for session close: add an End of Session
   flag into virtio_crypto_sym_crypt_op.

   I don't know whether this optimization is worth it but it's easy to
   implement and does not make the device more complex.

> 
> 1.3   Feature bits
> VIRTIO_CRYPTO_F_STATUS (0)    
>     Configuration status field is available. 
> VIRTIO_CRYPTO_F_MQ (1)
>       Device supports multiqueue to encrypt and decrypt.
> VIRTIO_CRYPTO_F_ALGS (2)
>     Configuration algorithms field is available.
> 
> 1.4   Device configuration layout
> Three driver-read-only configuration fields are currently defined. The status 
> only exists if VIRTIO_CRYPTO_F_STATUS is set. On read-only bit (for the 
> driver) is currently defined for the status field: VIRTIO_CRYPTO_S_HW_READY.
> #define VIRTIO_CRYPTO_S_HW_READY 1
> 
> The following driver-read-only field, max_virtqueues only exists if 
> VIRTIO_CRYPTO_F_MQ is set. This field specifies the maximum number of data 
> virtqueues (dataq1. . .dataqN) that can be configured once VIRTIO_CRYPTO_F_MQ 
> is negotiated.
> struct virtio_crypto_config {
>       le16 status;
>     le16 max_virtqueues;
>     le32 algorithms;
> }
> 
> The last driver-read-only field, algorithms only exists if 
> VIRTIO_CRYPTO_F_ALGS is set. This field specifies the algorithms which the 
> device offered once VIRTIO_CRYPTO_F_ALGS is negotiated. Two read-only bits 
> (for the driver) are currently defined for the algorithms field: 
> VIRTIO_CRYPTO_ALG_SYM and VIRTIO_CRYPTO_ALG_ASYM.
> #define VIRTIO_CRYPTO_ALG_SYM  (1 << 0)
> #define VIRTIO_CRYPTO_ALG_SYM  (1 << 1)
> 1.4.1 Device Requirements: Device configuration layout
> The device MUST set max_virtqueues to between 1 and 0x8000 inclusive, if it 
> offers VIRTIO_CRYPTO_F_MQ.
> If the driver does not negotiate the VIRTIO_CRYPTO_F_STATUS feature, it 
> SHOULD assume the hardware-backed implementation is ready, otherwise it 
> SHOULD read the ready status from the bottom bit of status.

Section 1.4.1 is for device requirements, please add a new section 1.4.2
for driver requirements.

> If the driver does not negotiate the VIRTIO_CRYPTO_F_ALGS feature, it SHOULD 
> assume the
> device support all algorithms.
> 1.5   Device Initialization
> A driver would perform a typical initialization routine like so:
> 1. Identify and initialize data virtqueue, up to N if VIRTIO_CRYPTO_F_MQ 
> feature bit is negotiated, N=max_virtqueues, otherwise identify N=1.
> 2. Identify the control virtqueue.
> 3. If the VIRTIO_CRYPTO_F_STATUS feature bit is negotiated, the ready status 
> of hardware-backend comes from the bottom bit of status. Otherwise, the 
> driver assumes it’s active.

How does a driver wait for the device to becomes ready without spinning?
I guess it would enable the configuration notification interrupt, then
read the status field to check for the bit, and then sleep until the
configuration interrupt occurs.

If the configuration space accesses become complex it may be better to
use a "Device Init" command on the control virtqueue instead.

> 4. If the VIRTIO_CRYPTO_F_ALGS feature bit is negotiated, the driver can read 
> the supported algorithms from bits of algorithms. Otherwise, the driver 
> assumes all algorithms are supported.
> 1.6   Device Operation
> 1.6.1 Session operation
> The symmetric algorithms have the concept of sessions. A session is a handle 
> which describes the
> cryptographic parameters to be applied to a number of buffers. The data 
> within a session handle includes the following:
> •1. The operation (cipher, hash or both, and if both, the order in which the 
> algorithms should be applied).
> •2. The cipher setup data, including the cipher algorithm and mode, the key 
> and its length, and the direction (encrypt or decrypt).
> •3. The hash setup data, including the hash algorithm, mode (plain, nested or 
> authenticated), and digest result length (to allow for truncation).
>       Authenticated mode can refer to HMAC, which requires that the key and 
> its length are also specified. It is also used for GCM and CCM authenticated 
> encryption, in which case the AAD length is also specified.
>       For nested mode, the inner and outer prefix data and length are 
> specified, as well as the outer hash algorithm.
> 
> The controlq virtqueue is used to control session operations, including 
> creation or close. The request is preceded by a header:
> struct virtio_crypto_sym_ctlhdr {
>     /* control type  */
>     u8 type;
> };
> Two bits are currently defined for the control header type: 
> enum virto_crypto_ctl_type {
>     VIRTIO_CRYPTO_CTRL_CREATE_SESSION = 1,
>     VIRTIO_CRYPTO_CTRL_CLOSE_SESSION = 2,
> };
> 
> 1.6.1.1 Session creation
> Firstly, the session creation request MUST be set the control type with 
> VIRTIO_CRYPTO_CTRL_CREATE_SESSION, then the request is preceded by an 
> operation header:
> typedef struct virtio_crypto_sym_session_op {
>       virtio_crypto_sym_op_type_t op_type;

sizeof(enum foo) is implementation-specific according to the C standard.
You must explicitly choose a type (u8, le16, le32) in this specification
so that the struct layout is compatible between compilers.

>     virtio_crypto_sym_cipher_t cipher_setup_data;
>     virtio_crypto_sym_hash_t hash_setup_data;
>     virtio_crypto_sym_alg_chain_order_t alg_chain_order;
>     u8 verify_digest;
> } virtio_crypto_sym_session_op_t;
> 
> And the structures definition details are:
> 
> typedef enum virtio_crypto_sym_op_type
> {
>     VIRTIO_CRYPTO_SYM_OP_NONE = 0,
>     /**< No operation */
>     VIRTIO_CRYPTO_SYM_OP_CIPHER,
>     /**< Cipher only operation on the data */
>     VIRTIO_CRYPTO_SYM_OP_HASH,
>     /**< Hash only operation on the data */
>     VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING
>     /**< Chain any cipher with any hash operation. The order depends on
>      * the value in the CpaCySymAlgChainOrder enum.
>      *
>      * This value is also used for authenticated ciphers (GCM and CCM), in
>      * which case the cipherAlgorithm should take one of the values @ref
>      * CPA_CY_SYM_CIPHER_AES_CCM or @ref CPA_CY_SYM_CIPHER_AES_GCM, while the
>      * hashAlgorithm should take the corresponding value @ref
>      * CPA_CY_SYM_HASH_AES_CCM or @ref CPA_CY_SYM_HASH_AES_GCM.
>      */
> } virtio_crypto_sym_op_type_t;
> 
> typedef enum virtio_crypto_sym_hash_mode
> {
>     VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN = 1,
>     /**< Plain hash.  Can be specified for MD5 and the SHA family of
>      * hash algorithms. */
>     VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH,
>     /**< Authenticated hash.  This mode may be used in conjunction with the
>      * MD5 and SHA family of algorithms to specify HMAC.  It MUST also be
>      * specified with all of the remaining algorithms, all of which are in
>      * fact authentication algorithms.
>      */
>     VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED
>     /**< Nested hash.  Can be specified for MD5 and the SHA family of
>      * hash algorithms. */
> } virtio_crypto_sym_hash_mode_t;
> 
> typedef struct virtio_crypto_sym_hash_auth_mode {
>       /* length of authenticated key */
>       le32 auth_key_len;
>       /* The length of the additional authenticated data (AAD) in bytes */
>       le32 aad_len;
> } virtio_crypto_sym_hash_auth_mode_t;
> 
> typedef struct virtio_crypto_sym_cipher {
>       /* cipher algorithm type (ie. aes-cbc ) */
>     enum virtio_crypto_cipher_alg alg;

You forgot to define virtio_crypto_cipher_alg.

>     /* length of key */
>     le32 keylen;
>     /* encrypt or decrypt */
>     u8 op;
> } virtio_crypto_sym_cipher_t;
> 
> typedef struct virtio_crypto_sym_hash {
>       /* hash algorithm type */
>     enum virtio_crypto_hash_alg hash_alg;
>     /* mode of hash operation, including authenticated/plain/nested hash */
>     virtio_crypto_sym_hash_mode_t hash_mode;
>       /* hash result length */
>     le32 hash_result_len;
>     virtio_crypto_sym_hash_auth_mode_t auth_mode_setup_data;
> } virtio_crypto_sym_hash_t;
> 
> typedef enum virtio_crypto_sym_alg_chain_order {
>       /* Perform the hash operation followed by the cipher operation */
>     VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER = 1,
>     /* Perform the cipher operation followed by the hash operation */
>     VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH
> } virtio_crypto_sym_alg_chain_order_t;
> When the device finish the processing of session close, the device MUST 
> return a session identifier to the driver. So the session creation request 
> MUST end by a tailer:

s/finish/finishes/

You used the word MUST.  This sentence belongs in a "Device
requirements" section.

> typedef struct virtio_crypto_sym_session_op_inhdr {
>       u8     status;
>       le64    session_id;
> } virtio_crypto_sym_session_op_inhdr_t;
> Both status and session_id are written by the device: either 
> VIRTIO_CRYPTO_CTRL_OK for success, VIRTIO_CRYPTO_CTRL_ERR for creation failed 
> or device error.
> enum {
>     VIRTIO_CRYPTO_CTRL_OK = 0,
>     VIRTIO_CRYPTO_CTRL_ERR = 1,
> };
> 
> 1.6.1.2 Session close
> The session close request MUST be set the control type with 
> VIRTIO_CRYPTO_CTRL_CLOSE_SESSION and pass the session_id to the device.
> 1.6.2 Encryption operation
> The encryption and decryption requests and the corresponding results are 
> transmitted by placing them in dataq. The symmetric algorithms requests are 
> preceded by a header:
> typedef struct virtio_crypto_sym_crypt_op {
>       /* the backend returned session identifier */
>       le64 session_id;
>     /* length of initial vector */
>       le32 iv_len;
>       /* iv offset in the whole crypto data memory */
>       le32 iv_offset;
>       /* length of additional auth data */
>       le32 auth_len;
>       /* additional auth data offset in the whole crypto data memory */
>       le32 additional_auth_offset;
>       /* cipher start source offest */
>       le32 cipher_start_src_offset;
>       le32 len_to_cipher;
>       /* hash start source offest */
>       le32 hash_start_src_offset;
>       le32 len_to_hash;
>       /* length of source data */
>       le32 source_len;
> } virtio_crypto_sym_crypt_op_t;
> 
> The data requests end by a status byte. The final status byte is written by 
> the device: either VIRTIO_CRYPTO_S_OK for success, VIRTIO_CRYPTO_S_ERR for 
> device or driver error, VIRTIO_CRYPTO_S_BADMSG for verification failed when 
> decrypt AEAD algorithms:
> #define VIRTIO_CRYPTO_S_OK    0
> #define VIRTIO_CRYPTO_S_ERR    1
> #define VIRTIO_CRYPTO_S_BADMSG    2
> 
> 1.6.2.1 Steps of encryption Operation
> Both ctrlq and dataq virtqueue are bidirectional.
> Step1: Create a session:
> 1.    The driver fill out the context message, include algorithm name, key, 
> keylen etc;

Grammar nits:

"The driver fills" (the same applies below for the verbs like "sends",
"creates", etc)

s/include/including/

> 2.    The driver send a context message to the backend device by controlq;
> 3.    The device create a session using the message transmitted by controlq;
> 4.    Return the session id to the driver. 
> Step 2: Execute the detail encryption operation:
> 1.    The driver fill out the encrypt requests;
> 2.    Put the requests into dataq and kick the virtqueue;
> 3.    The device execute the encryption operation according the requests’ 
> arguments;
> 4.    The device return the encryption result to the driver by dataq;
> 5.    The driver callback handle the result and over.
> 
> Note: the driver CAN support both synchronous and asynchronous encryption. 
> Then the performance is poor in synchronous operation because frequent 
> context switching and virtualization overhead. The driver SHOULD by 
> preference use asynchronous encryption.
> 1.6.3 Decryption Operation
> The decryption process is the same with encryption, except that the device 
> MUST verify and return the verify result to the driver. If the verify result 
> is not correct, VIRTIO_CRYPTO_S_BADMSG (bad message) SHOULD be returned the 
> driver.

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]