diff options
author | Gonglei <arei.gonglei@huawei.com> | 2018-03-01 21:46:30 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2018-03-01 18:26:17 +0200 |
commit | efbfeb81802cf9723a4663fadd674bf452a07e11 (patch) | |
tree | 128a4c8780e711464f863a2c9e59af6b67aa4426 /hw/virtio | |
parent | 5da73dabe86162005dec83a039102b126944f03a (diff) |
cryptodev-vhost-user: add crypto session handler
Introduce two vhost-user meassges: VHOST_USER_CREATE_CRYPTO_SESSION
and VHOST_USER_CLOSE_CRYPTO_SESSION. At this point, the QEMU side
support crypto operation in cryptodev host-user backend.
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
Signed-off-by: Jay Zhou <jianjay.zhou@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r-- | hw/virtio/vhost-user.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 6eb97980ad..41ff5cff41 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -17,6 +17,7 @@ #include "sysemu/kvm.h" #include "qemu/error-report.h" #include "qemu/sockets.h" +#include "sysemu/cryptodev.h" #include <sys/ioctl.h> #include <sys/socket.h> @@ -39,6 +40,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_NET_MTU = 4, VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_MAX }; @@ -72,6 +74,8 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_ENDIAN = 23, VHOST_USER_GET_CONFIG = 24, VHOST_USER_SET_CONFIG = 25, + VHOST_USER_CREATE_CRYPTO_SESSION = 26, + VHOST_USER_CLOSE_CRYPTO_SESSION = 27, VHOST_USER_MAX } VhostUserRequest; @@ -107,6 +111,17 @@ typedef struct VhostUserConfig { uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; } VhostUserConfig; +#define VHOST_CRYPTO_SYM_HMAC_MAX_KEY_LEN 512 +#define VHOST_CRYPTO_SYM_CIPHER_MAX_KEY_LEN 64 + +typedef struct VhostUserCryptoSession { + /* session id for success, -1 on errors */ + int64_t session_id; + CryptoDevBackendSymSessionInfo session_setup_data; + uint8_t key[VHOST_CRYPTO_SYM_CIPHER_MAX_KEY_LEN]; + uint8_t auth_key[VHOST_CRYPTO_SYM_HMAC_MAX_KEY_LEN]; +} VhostUserCryptoSession; + static VhostUserConfig c __attribute__ ((unused)); #define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \ + sizeof(c.size) \ @@ -132,6 +147,7 @@ typedef union { VhostUserLog log; struct vhost_iotlb_msg iotlb; VhostUserConfig config; + VhostUserCryptoSession session; } VhostUserPayload; typedef struct VhostUserMsg { @@ -1054,6 +1070,92 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, return 0; } +static int vhost_user_crypto_create_session(struct vhost_dev *dev, + void *session_info, + uint64_t *session_id) +{ + bool crypto_session = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); + CryptoDevBackendSymSessionInfo *sess_info = session_info; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_CREATE_CRYPTO_SESSION, + .hdr.flags = VHOST_USER_VERSION, + .hdr.size = sizeof(msg.payload.session), + }; + + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); + + if (!crypto_session) { + error_report("vhost-user trying to send unhandled ioctl"); + return -1; + } + + memcpy(&msg.payload.session.session_setup_data, sess_info, + sizeof(CryptoDevBackendSymSessionInfo)); + if (sess_info->key_len) { + memcpy(&msg.payload.session.key, sess_info->cipher_key, + sess_info->key_len); + } + if (sess_info->auth_key_len > 0) { + memcpy(&msg.payload.session.auth_key, sess_info->auth_key, + sess_info->auth_key_len); + } + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + error_report("vhost_user_write() return -1, create session failed"); + return -1; + } + + if (vhost_user_read(dev, &msg) < 0) { + error_report("vhost_user_read() return -1, create session failed"); + return -1; + } + + if (msg.hdr.request != VHOST_USER_CREATE_CRYPTO_SESSION) { + error_report("Received unexpected msg type. Expected %d received %d", + VHOST_USER_CREATE_CRYPTO_SESSION, msg.hdr.request); + return -1; + } + + if (msg.hdr.size != sizeof(msg.payload.session)) { + error_report("Received bad msg size."); + return -1; + } + + if (msg.payload.session.session_id < 0) { + error_report("Bad session id: %" PRId64 "", + msg.payload.session.session_id); + return -1; + } + *session_id = msg.payload.session.session_id; + + return 0; +} + +static int +vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) +{ + bool crypto_session = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); + VhostUserMsg msg = { + .hdr.request = VHOST_USER_CLOSE_CRYPTO_SESSION, + .hdr.flags = VHOST_USER_VERSION, + .hdr.size = sizeof(msg.payload.u64), + }; + msg.payload.u64 = session_id; + + if (!crypto_session) { + error_report("vhost-user trying to send unhandled ioctl"); + return -1; + } + + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + error_report("vhost_user_write() return -1, close session failed"); + return -1; + } + + return 0; +} + const VhostOps user_ops = { .backend_type = VHOST_BACKEND_TYPE_USER, .vhost_backend_init = vhost_user_init, @@ -1082,4 +1184,6 @@ const VhostOps user_ops = { .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg, .vhost_get_config = vhost_user_get_config, .vhost_set_config = vhost_user_set_config, + .vhost_crypto_create_session = vhost_user_crypto_create_session, + .vhost_crypto_close_session = vhost_user_crypto_close_session, }; |