Message ID | 1474272982-275836-5-git-send-email-arei.gonglei@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
AFAICT you are not using gcrypt here - you're using QEMU cipher APIs (which is good). These APIs can be backed by either nettle or gcrypt though, so the subject is misleading. Regards, Daniel
Hi Daniel, > -----Original Message----- > From: Daniel P. Berrange [mailto:berrange@redhat.com] > Sent: Monday, September 19, 2016 4:30 PM > Subject: Re: [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new > cryptodev backend > > AFAICT you are not using gcrypt here - you're using QEMU > cipher APIs (which is good). These APIs can be backed by > either nettle or gcrypt though, so the subject is misleading. > Oops, thanks for your reminding :) Will fix in the next version. Regards, -Gonglei
On Mon, Sep 19, 2016 at 04:16:16PM +0800, Gonglei wrote: > Signed-off-by: Gonglei <arei.gonglei@huawei.com> > --- > crypto/Makefile.objs | 1 + > crypto/cryptodev-gcrypt.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++ > qemu-options.hx | 18 +++ > 3 files changed, 348 insertions(+) > create mode 100644 crypto/cryptodev-gcrypt.c > > diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs > index f7f3c4f..bd8aea7 100644 > --- a/crypto/Makefile.objs > +++ b/crypto/Makefile.objs > @@ -27,6 +27,7 @@ crypto-obj-y += block.o > crypto-obj-y += block-qcow.o > crypto-obj-y += block-luks.o > crypto-obj-y += cryptodev.o > +crypto-obj-$(CONFIG_GCRYPT) += cryptodev-gcrypt.o This can be just crypto-obj-y += > # Let the userspace emulators avoid linking gnutls/etc > crypto-aes-obj-y = aes.o > diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c > new file mode 100644 > index 0000000..66a0e5e > --- /dev/null > +++ b/crypto/cryptodev-gcrypt.c > +/** > + * @TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT: > + * name of backend that uses gcrypt library > + */ > +#define TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT "cryptodev-backend-gcrypt" I'd suggest we just call this backend "builtin", so do a replace of "gcrypt" with "builtin" throughout. > +static void qcrypto_cryptodev_backend_gcrypt_init( > + QCryptoCryptoDevBackend *backend, Error **errp) > +{ > + /* Only support one queue */ > + int queues = MAX(backend->conf.peers.queues, 1); > + int i; Nitpick, I prefer to see 'size_t' for list iterators that are always positive. Similar comment in other places in this series using int i > + QCryptoCryptoDevBackendClientState *cc; > + > + for (i = 0; i < queues; i++) { > + cc = qcrypto_cryptodev_backend_new_client( > + "cryptodev-gcrypt", NULL); > + snprintf(cc->info_str, sizeof(cc->info_str), > + "cryptodev-gcrypt%d", i); > + cc->queue_index = i; > + > + backend->conf.peers.ccs[i] = cc; > + } > + > + backend->conf.crypto_services = > + 1u << VIRTIO_CRYPTO_SERVICE_CIPHER | > + 1u << VIRTIO_CRYPTO_SERVICE_HASH | > + 1u << VIRTIO_CRYPTO_SERVICE_MAC; > + backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC; > + backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1; > +} > + > +static int > +qcrypto_cryptodev_backend_gcrypt_get_unused_session_index( > + QCryptoCryptoDevBackendGcrypt *gcrypt) > +{ > + int i; > + > + for (i = 0; i < MAX_NUM_SESSIONS; i++) { > + if (gcrypt->sessions[i] == NULL) { > + return i; > + } > + } > + > + return -1; > +} > + > +static int qcrypto_cryptodev_backend_gcrypt_create_cipher_session( > + QCryptoCryptoDevBackendGcrypt *gcrypt, > + QCryptoCryptoDevBackendSymSessionInfo *sess_info, > + Error **errp) > +{ > + int algo; > + int mode; > + QCryptoCipher *cipher; > + int index; > + QCryptoCryptoDevBackendGcryptSession *sess; > + > + if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) { > + error_setg(errp, "unsupported optype :%u", sess_info->op_type); > + return -1; > + } > + > + index = qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(gcrypt); > + if (index < 0) { > + error_setg(errp, "the total number of created session exceed %u", > + MAX_NUM_SESSIONS); > + return -1; > + } > + > + switch (sess_info->cipher_alg) { > + case VIRTIO_CRYPTO_CIPHER_AES_ECB: > + if (sess_info->key_len == 128 / 8) { > + algo = QCRYPTO_CIPHER_ALG_AES_128; > + } else if (sess_info->key_len == 192 / 8) { > + algo = QCRYPTO_CIPHER_ALG_AES_192; > + } else if (sess_info->key_len == 256 / 8) { > + algo = QCRYPTO_CIPHER_ALG_AES_256; > + } else { > + error_setg(errp, "unsupported key length :%u", > + sess_info->key_len); > + return -1; > + } > + mode = QCRYPTO_CIPHER_MODE_ECB; > + break; > + case VIRTIO_CRYPTO_CIPHER_AES_CBC: > + if (sess_info->key_len == 128 / 8) { > + algo = QCRYPTO_CIPHER_ALG_AES_128; > + } else if (sess_info->key_len == 192 / 8) { > + algo = QCRYPTO_CIPHER_ALG_AES_192; > + } else if (sess_info->key_len == 256 / 8) { > + algo = QCRYPTO_CIPHER_ALG_AES_256; > + } else { > + error_setg(errp, "unsupported key length :%u", > + sess_info->key_len); > + return -1; > + } > + mode = QCRYPTO_CIPHER_MODE_CBC; > + break; > + case VIRTIO_CRYPTO_CIPHER_AES_CTR: Although the QEMU cipher.h API does not export CTR mode currently it should be trivial to add it. So feel free to add a patch at the start of the series implementing CTR mode in the cipher API. Both gcrypt and nettle have support for it which is all we need. > + default: > + error_setg(errp, "unsupported cipher alg :%u", > + sess_info->cipher_alg); > + return -1; > + } > + > + cipher = qcrypto_cipher_new(algo, mode, > + sess_info->cipher_key, > + sess_info->key_len, > + errp); > + if (!cipher) { > + return -1; > + } > + > + sess = g_new0(QCryptoCryptoDevBackendGcryptSession, 1); > + sess->cipher = cipher; > + sess->direction = sess_info->direction; > + sess->type = sess_info->op_type; > + > + gcrypt->sessions[index] = sess; > + > + return index; > +} > + > +static int64_t qcrypto_cryptodev_backend_gcrypt_sym_create_session( > + QCryptoCryptoDevBackend *backend, > + QCryptoCryptoDevBackendSymSessionInfo *sess_info, > + uint32_t queue_index, Error **errp) > +{ > + QCryptoCryptoDevBackendGcrypt *gcrypt = > + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); > + int64_t session_id = -1; > + int ret; > + > + switch (sess_info->op_code) { > + case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION: > + ret = qcrypto_cryptodev_backend_gcrypt_create_cipher_session( > + gcrypt, sess_info, errp); > + if (ret < 0) { > + return ret; > + } else { > + session_id = ret; > + } > + break; > + case VIRTIO_CRYPTO_HASH_CREATE_SESSION: > + case VIRTIO_CRYPTO_MAC_CREATE_SESSION: > + default: > + error_setg(errp, "unsupported opcode :%" PRIu32 "", > + sess_info->op_code); > + return -1; > + } > + > + return session_id; > +} > + > +static int qcrypto_cryptodev_backend_gcrypt_sym_close_session( > + QCryptoCryptoDevBackend *backend, > + uint64_t session_id, Error **errp) > +{ > + QCryptoCryptoDevBackendGcrypt *gcrypt = > + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); > + > + if (session_id >= MAX_NUM_SESSIONS || > + gcrypt->sessions[session_id] == NULL) { > + error_setg(errp, "Cannot find a valid session id: %" PRIu64 "", > + session_id); > + return -1; > + } > + > + qcrypto_cipher_free(gcrypt->sessions[session_id]->cipher); > + g_free(gcrypt->sessions[session_id]); > + gcrypt->sessions[session_id] = NULL; > + return 0; > +} > + > +static int qcrypto_cryptodev_backend_gcrypt_sym_operation( > + QCryptoCryptoDevBackend *backend, > + QCryptoCryptoDevBackendSymOpInfo *op_info, > + uint32_t queue_index, Error **errp) > +{ > + QCryptoCryptoDevBackendGcrypt *gcrypt = > + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); > + QCryptoCryptoDevBackendGcryptSession *sess; > + int ret; > + > + if (op_info->session_id >= MAX_NUM_SESSIONS || > + gcrypt->sessions[op_info->session_id] == NULL) { > + error_setg(errp, "Cannot find a valid session id: %" PRIu64 "", > + op_info->session_id); > + return -VIRTIO_CRYPTO_OP_INVSESS; > + } > + > + sess = gcrypt->sessions[op_info->session_id]; > + > + ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv, > + op_info->iv_len, errp); > + if (ret < 0) { > + return -VIRTIO_CRYPTO_OP_ERR; > + } > + > + if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) { > + ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src, > + op_info->dst, op_info->src_len, errp); > + if (ret < 0) { > + return -VIRTIO_CRYPTO_OP_ERR; > + } > + } else { > + ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src, > + op_info->dst, op_info->src_len, errp); > + if (ret < 0) { > + return -VIRTIO_CRYPTO_OP_ERR; > + } > + } > + return 0; > +} Regards, Daniel
> -----Original Message----- > From: Daniel P. Berrange [mailto:berrange@redhat.com] > Sent: Monday, September 19, 2016 4:56 PM > Subject: Re: [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new > cryptodev backend > > On Mon, Sep 19, 2016 at 04:16:16PM +0800, Gonglei wrote: > > Signed-off-by: Gonglei <arei.gonglei@huawei.com> > > --- > > crypto/Makefile.objs | 1 + > > crypto/cryptodev-gcrypt.c | 329 > ++++++++++++++++++++++++++++++++++++++++++++++ > > qemu-options.hx | 18 +++ > > 3 files changed, 348 insertions(+) > > create mode 100644 crypto/cryptodev-gcrypt.c > > > > diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs > > index f7f3c4f..bd8aea7 100644 > > --- a/crypto/Makefile.objs > > +++ b/crypto/Makefile.objs > > @@ -27,6 +27,7 @@ crypto-obj-y += block.o > > crypto-obj-y += block-qcow.o > > crypto-obj-y += block-luks.o > > crypto-obj-y += cryptodev.o > > +crypto-obj-$(CONFIG_GCRYPT) += cryptodev-gcrypt.o > > This can be just crypto-obj-y += > Yes. > > # Let the userspace emulators avoid linking gnutls/etc > > crypto-aes-obj-y = aes.o > > diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c > > new file mode 100644 > > index 0000000..66a0e5e > > --- /dev/null > > +++ b/crypto/cryptodev-gcrypt.c > > +/** > > + * @TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT: > > + * name of backend that uses gcrypt library > > + */ > > +#define TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT > "cryptodev-backend-gcrypt" > > I'd suggest we just call this backend "builtin", so do a > replace of "gcrypt" with "builtin" throughout. > OK, good name ;) > > +static void qcrypto_cryptodev_backend_gcrypt_init( > > + QCryptoCryptoDevBackend *backend, Error **errp) > > +{ > > + /* Only support one queue */ > > + int queues = MAX(backend->conf.peers.queues, 1); > > + int i; > > Nitpick, I prefer to see 'size_t' for list iterators > that are always positive. Similar comment in other > places in this series using int i > OK > > + QCryptoCryptoDevBackendClientState *cc; > > + > > + for (i = 0; i < queues; i++) { > > + cc = qcrypto_cryptodev_backend_new_client( > > + "cryptodev-gcrypt", NULL); > > + snprintf(cc->info_str, sizeof(cc->info_str), > > + "cryptodev-gcrypt%d", i); > > + cc->queue_index = i; > > + > > + backend->conf.peers.ccs[i] = cc; > > + } > > + > > + backend->conf.crypto_services = > > + 1u << VIRTIO_CRYPTO_SERVICE_CIPHER | > > + 1u << VIRTIO_CRYPTO_SERVICE_HASH | > > + 1u << VIRTIO_CRYPTO_SERVICE_MAC; > > + backend->conf.cipher_algo_l = 1u << > VIRTIO_CRYPTO_CIPHER_AES_CBC; > > + backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1; > > +} > > + > > +static int > > +qcrypto_cryptodev_backend_gcrypt_get_unused_session_index( > > + QCryptoCryptoDevBackendGcrypt *gcrypt) > > +{ > > + int i; > > + > > + for (i = 0; i < MAX_NUM_SESSIONS; i++) { > > + if (gcrypt->sessions[i] == NULL) { > > + return i; > > + } > > + } > > + > > + return -1; > > +} > > + > > +static int qcrypto_cryptodev_backend_gcrypt_create_cipher_session( > > + QCryptoCryptoDevBackendGcrypt *gcrypt, > > + QCryptoCryptoDevBackendSymSessionInfo > *sess_info, > > + Error **errp) > > +{ > > + int algo; > > + int mode; > > + QCryptoCipher *cipher; > > + int index; > > + QCryptoCryptoDevBackendGcryptSession *sess; > > + > > + if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) { > > + error_setg(errp, "unsupported optype :%u", sess_info->op_type); > > + return -1; > > + } > > + > > + index = > qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(gcrypt); > > + if (index < 0) { > > + error_setg(errp, "the total number of created session > exceed %u", > > + MAX_NUM_SESSIONS); > > + return -1; > > + } > > + > > + switch (sess_info->cipher_alg) { > > + case VIRTIO_CRYPTO_CIPHER_AES_ECB: > > + if (sess_info->key_len == 128 / 8) { > > + algo = QCRYPTO_CIPHER_ALG_AES_128; > > + } else if (sess_info->key_len == 192 / 8) { > > + algo = QCRYPTO_CIPHER_ALG_AES_192; > > + } else if (sess_info->key_len == 256 / 8) { > > + algo = QCRYPTO_CIPHER_ALG_AES_256; > > + } else { > > + error_setg(errp, "unsupported key length :%u", > > + sess_info->key_len); > > + return -1; > > + } > > + mode = QCRYPTO_CIPHER_MODE_ECB; > > + break; > > + case VIRTIO_CRYPTO_CIPHER_AES_CBC: > > + if (sess_info->key_len == 128 / 8) { > > + algo = QCRYPTO_CIPHER_ALG_AES_128; > > + } else if (sess_info->key_len == 192 / 8) { > > + algo = QCRYPTO_CIPHER_ALG_AES_192; > > + } else if (sess_info->key_len == 256 / 8) { > > + algo = QCRYPTO_CIPHER_ALG_AES_256; > > + } else { > > + error_setg(errp, "unsupported key length :%u", > > + sess_info->key_len); > > + return -1; > > + } > > + mode = QCRYPTO_CIPHER_MODE_CBC; > > + break; > > + case VIRTIO_CRYPTO_CIPHER_AES_CTR: > > Although the QEMU cipher.h API does not export CTR mode currently > it should be trivial to add it. So feel free to add a patch at > the start of the series implementing CTR mode in the cipher API. > Both gcrypt and nettle have support for it which is all we need. > OK, will do. Thanks, -Gonglei
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs index f7f3c4f..bd8aea7 100644 --- a/crypto/Makefile.objs +++ b/crypto/Makefile.objs @@ -27,6 +27,7 @@ crypto-obj-y += block.o crypto-obj-y += block-qcow.o crypto-obj-y += block-luks.o crypto-obj-y += cryptodev.o +crypto-obj-$(CONFIG_GCRYPT) += cryptodev-gcrypt.o # Let the userspace emulators avoid linking gnutls/etc crypto-aes-obj-y = aes.o diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c new file mode 100644 index 0000000..66a0e5e --- /dev/null +++ b/crypto/cryptodev-gcrypt.c @@ -0,0 +1,329 @@ +/* + * QEMU Cryptodev backend for gcrypt + * + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + * Gonglei <arei.gonglei@huawei.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "qemu/osdep.h" +#include "crypto/cryptodev.h" +#include "hw/boards.h" +#include "qapi/error.h" +#include "standard-headers/linux/virtio_crypto.h" +#include "crypto/cipher.h" + + +/** + * @TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT: + * name of backend that uses gcrypt library + */ +#define TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT "cryptodev-backend-gcrypt" + +#define QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(obj) \ + OBJECT_CHECK(QCryptoCryptoDevBackendGcrypt, \ + (obj), TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT) + +typedef struct QCryptoCryptoDevBackendGcrypt + QCryptoCryptoDevBackendGcrypt; + +typedef struct QCryptoCryptoDevBackendGcryptSession { + QCryptoCipher *cipher; + uint8_t direction; /* encryption or decryption */ + uint8_t type; /* cipher? hash? aead? */ + QTAILQ_ENTRY(QCryptoCryptoDevBackendGcryptSession) next; +} QCryptoCryptoDevBackendGcryptSession; + +/* Max number of symetrical sessions */ +#define MAX_NUM_SESSIONS 256 + + +struct QCryptoCryptoDevBackendGcrypt { + QCryptoCryptoDevBackend parent_obj; + + QCryptoCryptoDevBackendGcryptSession *sessions[MAX_NUM_SESSIONS]; +}; + +static void qcrypto_cryptodev_backend_gcrypt_init( + QCryptoCryptoDevBackend *backend, Error **errp) +{ + /* Only support one queue */ + int queues = MAX(backend->conf.peers.queues, 1); + int i; + QCryptoCryptoDevBackendClientState *cc; + + for (i = 0; i < queues; i++) { + cc = qcrypto_cryptodev_backend_new_client( + "cryptodev-gcrypt", NULL); + snprintf(cc->info_str, sizeof(cc->info_str), + "cryptodev-gcrypt%d", i); + cc->queue_index = i; + + backend->conf.peers.ccs[i] = cc; + } + + backend->conf.crypto_services = + 1u << VIRTIO_CRYPTO_SERVICE_CIPHER | + 1u << VIRTIO_CRYPTO_SERVICE_HASH | + 1u << VIRTIO_CRYPTO_SERVICE_MAC; + backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC; + backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1; +} + +static int +qcrypto_cryptodev_backend_gcrypt_get_unused_session_index( + QCryptoCryptoDevBackendGcrypt *gcrypt) +{ + int i; + + for (i = 0; i < MAX_NUM_SESSIONS; i++) { + if (gcrypt->sessions[i] == NULL) { + return i; + } + } + + return -1; +} + +static int qcrypto_cryptodev_backend_gcrypt_create_cipher_session( + QCryptoCryptoDevBackendGcrypt *gcrypt, + QCryptoCryptoDevBackendSymSessionInfo *sess_info, + Error **errp) +{ + int algo; + int mode; + QCryptoCipher *cipher; + int index; + QCryptoCryptoDevBackendGcryptSession *sess; + + if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) { + error_setg(errp, "unsupported optype :%u", sess_info->op_type); + return -1; + } + + index = qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(gcrypt); + if (index < 0) { + error_setg(errp, "the total number of created session exceed %u", + MAX_NUM_SESSIONS); + return -1; + } + + switch (sess_info->cipher_alg) { + case VIRTIO_CRYPTO_CIPHER_AES_ECB: + if (sess_info->key_len == 128 / 8) { + algo = QCRYPTO_CIPHER_ALG_AES_128; + } else if (sess_info->key_len == 192 / 8) { + algo = QCRYPTO_CIPHER_ALG_AES_192; + } else if (sess_info->key_len == 256 / 8) { + algo = QCRYPTO_CIPHER_ALG_AES_256; + } else { + error_setg(errp, "unsupported key length :%u", + sess_info->key_len); + return -1; + } + mode = QCRYPTO_CIPHER_MODE_ECB; + break; + case VIRTIO_CRYPTO_CIPHER_AES_CBC: + if (sess_info->key_len == 128 / 8) { + algo = QCRYPTO_CIPHER_ALG_AES_128; + } else if (sess_info->key_len == 192 / 8) { + algo = QCRYPTO_CIPHER_ALG_AES_192; + } else if (sess_info->key_len == 256 / 8) { + algo = QCRYPTO_CIPHER_ALG_AES_256; + } else { + error_setg(errp, "unsupported key length :%u", + sess_info->key_len); + return -1; + } + mode = QCRYPTO_CIPHER_MODE_CBC; + break; + case VIRTIO_CRYPTO_CIPHER_AES_CTR: + default: + error_setg(errp, "unsupported cipher alg :%u", + sess_info->cipher_alg); + return -1; + } + + cipher = qcrypto_cipher_new(algo, mode, + sess_info->cipher_key, + sess_info->key_len, + errp); + if (!cipher) { + return -1; + } + + sess = g_new0(QCryptoCryptoDevBackendGcryptSession, 1); + sess->cipher = cipher; + sess->direction = sess_info->direction; + sess->type = sess_info->op_type; + + gcrypt->sessions[index] = sess; + + return index; +} + +static int64_t qcrypto_cryptodev_backend_gcrypt_sym_create_session( + QCryptoCryptoDevBackend *backend, + QCryptoCryptoDevBackendSymSessionInfo *sess_info, + uint32_t queue_index, Error **errp) +{ + QCryptoCryptoDevBackendGcrypt *gcrypt = + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); + int64_t session_id = -1; + int ret; + + switch (sess_info->op_code) { + case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION: + ret = qcrypto_cryptodev_backend_gcrypt_create_cipher_session( + gcrypt, sess_info, errp); + if (ret < 0) { + return ret; + } else { + session_id = ret; + } + break; + case VIRTIO_CRYPTO_HASH_CREATE_SESSION: + case VIRTIO_CRYPTO_MAC_CREATE_SESSION: + default: + error_setg(errp, "unsupported opcode :%" PRIu32 "", + sess_info->op_code); + return -1; + } + + return session_id; +} + +static int qcrypto_cryptodev_backend_gcrypt_sym_close_session( + QCryptoCryptoDevBackend *backend, + uint64_t session_id, Error **errp) +{ + QCryptoCryptoDevBackendGcrypt *gcrypt = + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); + + if (session_id >= MAX_NUM_SESSIONS || + gcrypt->sessions[session_id] == NULL) { + error_setg(errp, "Cannot find a valid session id: %" PRIu64 "", + session_id); + return -1; + } + + qcrypto_cipher_free(gcrypt->sessions[session_id]->cipher); + g_free(gcrypt->sessions[session_id]); + gcrypt->sessions[session_id] = NULL; + return 0; +} + +static int qcrypto_cryptodev_backend_gcrypt_sym_operation( + QCryptoCryptoDevBackend *backend, + QCryptoCryptoDevBackendSymOpInfo *op_info, + uint32_t queue_index, Error **errp) +{ + QCryptoCryptoDevBackendGcrypt *gcrypt = + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); + QCryptoCryptoDevBackendGcryptSession *sess; + int ret; + + if (op_info->session_id >= MAX_NUM_SESSIONS || + gcrypt->sessions[op_info->session_id] == NULL) { + error_setg(errp, "Cannot find a valid session id: %" PRIu64 "", + op_info->session_id); + return -VIRTIO_CRYPTO_OP_INVSESS; + } + + sess = gcrypt->sessions[op_info->session_id]; + + ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv, + op_info->iv_len, errp); + if (ret < 0) { + return -VIRTIO_CRYPTO_OP_ERR; + } + + if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) { + ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src, + op_info->dst, op_info->src_len, errp); + if (ret < 0) { + return -VIRTIO_CRYPTO_OP_ERR; + } + } else { + ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src, + op_info->dst, op_info->src_len, errp); + if (ret < 0) { + return -VIRTIO_CRYPTO_OP_ERR; + } + } + return 0; +} + +static void qcrypto_cryptodev_backend_gcrypt_cleanup( + QCryptoCryptoDevBackend *backend, + Error **errp) +{ + QCryptoCryptoDevBackendGcrypt *gcrypt = + QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend); + int i; + int queues = backend->conf.peers.queues; + QCryptoCryptoDevBackendClientState *cc; + + for (i = 0; i < MAX_NUM_SESSIONS; i++) { + if (gcrypt->sessions[i] != NULL) { + qcrypto_cryptodev_backend_gcrypt_sym_close_session( + backend, i, errp); + } + } + + for (i = 0; i < queues; i++) { + cc = backend->conf.peers.ccs[i]; + if (cc) { + qcrypto_cryptodev_backend_free_client(cc); + backend->conf.peers.ccs[i] = NULL; + } + } +} + +static void qcrypto_cryptodev_backend_gcrypt_finalize(Object *obj) +{ + +} + +static void +qcrypto_cryptodev_backend_gcrypt_class_init(ObjectClass *oc, void *data) +{ + QCryptoCryptoDevBackendClass *bc = QCRYPTO_CRYPTODEV_BACKEND_CLASS(oc); + + bc->init = qcrypto_cryptodev_backend_gcrypt_init; + bc->cleanup = qcrypto_cryptodev_backend_gcrypt_cleanup; + bc->create_session = qcrypto_cryptodev_backend_gcrypt_sym_create_session; + bc->close_session = qcrypto_cryptodev_backend_gcrypt_sym_close_session; + bc->do_sym_op = qcrypto_cryptodev_backend_gcrypt_sym_operation; +} + +static const TypeInfo qcrypto_cryptodev_backend_gcrypt_info = { + .name = TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT, + .parent = TYPE_QCRYPTO_CRYPTODEV_BACKEND, + .class_init = qcrypto_cryptodev_backend_gcrypt_class_init, + .instance_finalize = qcrypto_cryptodev_backend_gcrypt_finalize, + .instance_size = sizeof(QCryptoCryptoDevBackendGcrypt), +}; + +static void +qcrypto_cryptodev_backend_gcrypt_register_types(void) +{ + type_register_static(&qcrypto_cryptodev_backend_gcrypt_info); +} + +type_init(qcrypto_cryptodev_backend_gcrypt_register_types); diff --git a/qemu-options.hx b/qemu-options.hx index a71aaf8..aff1217 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3887,6 +3887,24 @@ Dump the network traffic on netdev @var{dev} to the file specified by The file format is libpcap, so it can be analyzed with tools such as tcpdump or Wireshark. +@item -object cryptodev-backend-gcrypt,id=@var{id}[,queues=@var{queues}] + +Creates a cryptodev backend which executes crypto opreation from +the gcrypt library on the host. The @var{id} parameter is +a unique ID that will be used to reference this cryptodev backend from +the @option{virtio-crypto} device. The @var{queues} parameter is optional, +which specify the queue number of cryptodev backend, the default of +@var{queues} is 1. + +@example + + # qemu-system-x86_64 \ + [...] \ + -object cryptodev-backend-gcrypt,id=cryptodev0 \ + -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \ + [...] +@end example + @item -object secret,id=@var{id},data=@var{string},format=@var{raw|base64}[,keyid=@var{secretid},iv=@var{string}] @item -object secret,id=@var{id},file=@var{filename},format=@var{raw|base64}[,keyid=@var{secretid},iv=@var{string}]
Signed-off-by: Gonglei <arei.gonglei@huawei.com> --- crypto/Makefile.objs | 1 + crypto/cryptodev-gcrypt.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 18 +++ 3 files changed, 348 insertions(+) create mode 100644 crypto/cryptodev-gcrypt.c