1d0ee7a13SGonglei /* 2d0ee7a13SGonglei * QEMU Crypto Device Implementation 3d0ee7a13SGonglei * 4d0ee7a13SGonglei * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5d0ee7a13SGonglei * 6d0ee7a13SGonglei * Authors: 7d0ee7a13SGonglei * Gonglei <arei.gonglei@huawei.com> 8d0ee7a13SGonglei * 9d0ee7a13SGonglei * This library is free software; you can redistribute it and/or 10d0ee7a13SGonglei * modify it under the terms of the GNU Lesser General Public 11d0ee7a13SGonglei * License as published by the Free Software Foundation; either 12d0ee7a13SGonglei * version 2 of the License, or (at your option) any later version. 13d0ee7a13SGonglei * 14d0ee7a13SGonglei * This library is distributed in the hope that it will be useful, 15d0ee7a13SGonglei * but WITHOUT ANY WARRANTY; without even the implied warranty of 16d0ee7a13SGonglei * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17d0ee7a13SGonglei * Lesser General Public License for more details. 18d0ee7a13SGonglei * 19d0ee7a13SGonglei * You should have received a copy of the GNU Lesser General Public 20d0ee7a13SGonglei * License along with this library; if not, see <http://www.gnu.org/licenses/>. 21d0ee7a13SGonglei * 22d0ee7a13SGonglei */ 23d0ee7a13SGonglei #ifndef CRYPTODEV_H 24d0ee7a13SGonglei #define CRYPTODEV_H 25d0ee7a13SGonglei 26*dc5e9ac7SMarkus Armbruster #include "qemu/queue.h" 27d0ee7a13SGonglei #include "qom/object.h" 28d0ee7a13SGonglei 29d0ee7a13SGonglei /** 30d0ee7a13SGonglei * CryptoDevBackend: 31d0ee7a13SGonglei * 32d0ee7a13SGonglei * The CryptoDevBackend object is an interface 33d0ee7a13SGonglei * for different cryptodev backends, which provides crypto 34d0ee7a13SGonglei * operation wrapper. 35d0ee7a13SGonglei * 36d0ee7a13SGonglei */ 37d0ee7a13SGonglei 38d0ee7a13SGonglei #define TYPE_CRYPTODEV_BACKEND "cryptodev-backend" 39d0ee7a13SGonglei 40d0ee7a13SGonglei #define CRYPTODEV_BACKEND(obj) \ 41d0ee7a13SGonglei OBJECT_CHECK(CryptoDevBackend, \ 42d0ee7a13SGonglei (obj), TYPE_CRYPTODEV_BACKEND) 43d0ee7a13SGonglei #define CRYPTODEV_BACKEND_GET_CLASS(obj) \ 44d0ee7a13SGonglei OBJECT_GET_CLASS(CryptoDevBackendClass, \ 45d0ee7a13SGonglei (obj), TYPE_CRYPTODEV_BACKEND) 46d0ee7a13SGonglei #define CRYPTODEV_BACKEND_CLASS(klass) \ 47d0ee7a13SGonglei OBJECT_CLASS_CHECK(CryptoDevBackendClass, \ 48d0ee7a13SGonglei (klass), TYPE_CRYPTODEV_BACKEND) 49d0ee7a13SGonglei 50d0ee7a13SGonglei 51d0ee7a13SGonglei #define MAX_CRYPTO_QUEUE_NUM 64 52d0ee7a13SGonglei 53d0ee7a13SGonglei typedef struct CryptoDevBackendConf CryptoDevBackendConf; 54d0ee7a13SGonglei typedef struct CryptoDevBackendPeers CryptoDevBackendPeers; 55d0ee7a13SGonglei typedef struct CryptoDevBackendClient 56d0ee7a13SGonglei CryptoDevBackendClient; 57d0ee7a13SGonglei typedef struct CryptoDevBackend CryptoDevBackend; 58d0ee7a13SGonglei 599e4f86a8SGonglei enum CryptoDevBackendAlgType { 609e4f86a8SGonglei CRYPTODEV_BACKEND_ALG_SYM, 619e4f86a8SGonglei CRYPTODEV_BACKEND_ALG__MAX, 629e4f86a8SGonglei }; 639e4f86a8SGonglei 649e4f86a8SGonglei /** 659e4f86a8SGonglei * CryptoDevBackendSymSessionInfo: 669e4f86a8SGonglei * 679e4f86a8SGonglei * @op_code: operation code (refer to virtio_crypto.h) 689e4f86a8SGonglei * @cipher_alg: algorithm type of CIPHER 699e4f86a8SGonglei * @key_len: byte length of cipher key 709e4f86a8SGonglei * @hash_alg: algorithm type of HASH/MAC 719e4f86a8SGonglei * @hash_result_len: byte length of HASH operation result 729e4f86a8SGonglei * @auth_key_len: byte length of authenticated key 739e4f86a8SGonglei * @add_len: byte length of additional authenticated data 749e4f86a8SGonglei * @op_type: operation type (refer to virtio_crypto.h) 759e4f86a8SGonglei * @direction: encryption or direction for CIPHER 769e4f86a8SGonglei * @hash_mode: HASH mode for HASH operation (refer to virtio_crypto.h) 779e4f86a8SGonglei * @alg_chain_order: order of algorithm chaining (CIPHER then HASH, 789e4f86a8SGonglei * or HASH then CIPHER) 799e4f86a8SGonglei * @cipher_key: point to a key of CIPHER 809e4f86a8SGonglei * @auth_key: point to an authenticated key of MAC 819e4f86a8SGonglei * 829e4f86a8SGonglei */ 839e4f86a8SGonglei typedef struct CryptoDevBackendSymSessionInfo { 849e4f86a8SGonglei /* corresponding with virtio crypto spec */ 859e4f86a8SGonglei uint32_t op_code; 869e4f86a8SGonglei uint32_t cipher_alg; 879e4f86a8SGonglei uint32_t key_len; 889e4f86a8SGonglei uint32_t hash_alg; 899e4f86a8SGonglei uint32_t hash_result_len; 909e4f86a8SGonglei uint32_t auth_key_len; 919e4f86a8SGonglei uint32_t add_len; 929e4f86a8SGonglei uint8_t op_type; 939e4f86a8SGonglei uint8_t direction; 949e4f86a8SGonglei uint8_t hash_mode; 959e4f86a8SGonglei uint8_t alg_chain_order; 969e4f86a8SGonglei uint8_t *cipher_key; 979e4f86a8SGonglei uint8_t *auth_key; 989e4f86a8SGonglei } CryptoDevBackendSymSessionInfo; 999e4f86a8SGonglei 1009e4f86a8SGonglei /** 1019e4f86a8SGonglei * CryptoDevBackendSymOpInfo: 1029e4f86a8SGonglei * 1039e4f86a8SGonglei * @session_id: session index which was previously 1049e4f86a8SGonglei * created by cryptodev_backend_sym_create_session() 1059e4f86a8SGonglei * @aad_len: byte length of additional authenticated data 1069e4f86a8SGonglei * @iv_len: byte length of initialization vector or counter 1079e4f86a8SGonglei * @src_len: byte length of source data 1089e4f86a8SGonglei * @dst_len: byte length of destination data 1099e4f86a8SGonglei * @digest_result_len: byte length of hash digest result 1109e4f86a8SGonglei * @hash_start_src_offset: Starting point for hash processing, specified 1119e4f86a8SGonglei * as number of bytes from start of packet in source data, only used for 1129e4f86a8SGonglei * algorithm chain 1139e4f86a8SGonglei * @cipher_start_src_offset: Starting point for cipher processing, specified 1149e4f86a8SGonglei * as number of bytes from start of packet in source data, only used for 1159e4f86a8SGonglei * algorithm chain 1169e4f86a8SGonglei * @len_to_hash: byte length of source data on which the hash 1179e4f86a8SGonglei * operation will be computed, only used for algorithm chain 1189e4f86a8SGonglei * @len_to_cipher: byte length of source data on which the cipher 1199e4f86a8SGonglei * operation will be computed, only used for algorithm chain 1209e4f86a8SGonglei * @op_type: operation type (refer to virtio_crypto.h) 1219e4f86a8SGonglei * @iv: point to the initialization vector or counter 1229e4f86a8SGonglei * @src: point to the source data 1239e4f86a8SGonglei * @dst: point to the destination data 1249e4f86a8SGonglei * @aad_data: point to the additional authenticated data 1259e4f86a8SGonglei * @digest_result: point to the digest result data 1269e4f86a8SGonglei * @data[0]: point to the extensional memory by one memory allocation 1279e4f86a8SGonglei * 1289e4f86a8SGonglei */ 1299e4f86a8SGonglei typedef struct CryptoDevBackendSymOpInfo { 1309e4f86a8SGonglei uint64_t session_id; 1319e4f86a8SGonglei uint32_t aad_len; 1329e4f86a8SGonglei uint32_t iv_len; 1339e4f86a8SGonglei uint32_t src_len; 1349e4f86a8SGonglei uint32_t dst_len; 1359e4f86a8SGonglei uint32_t digest_result_len; 1369e4f86a8SGonglei uint32_t hash_start_src_offset; 1379e4f86a8SGonglei uint32_t cipher_start_src_offset; 1389e4f86a8SGonglei uint32_t len_to_hash; 1399e4f86a8SGonglei uint32_t len_to_cipher; 1409e4f86a8SGonglei uint8_t op_type; 1419e4f86a8SGonglei uint8_t *iv; 1429e4f86a8SGonglei uint8_t *src; 1439e4f86a8SGonglei uint8_t *dst; 1449e4f86a8SGonglei uint8_t *aad_data; 1459e4f86a8SGonglei uint8_t *digest_result; 1469e4f86a8SGonglei uint8_t data[0]; 1479e4f86a8SGonglei } CryptoDevBackendSymOpInfo; 148d0ee7a13SGonglei 149d0ee7a13SGonglei typedef struct CryptoDevBackendClass { 150d0ee7a13SGonglei ObjectClass parent_class; 151d0ee7a13SGonglei 152d0ee7a13SGonglei void (*init)(CryptoDevBackend *backend, Error **errp); 153d0ee7a13SGonglei void (*cleanup)(CryptoDevBackend *backend, Error **errp); 1549e4f86a8SGonglei 1559e4f86a8SGonglei int64_t (*create_session)(CryptoDevBackend *backend, 1569e4f86a8SGonglei CryptoDevBackendSymSessionInfo *sess_info, 1579e4f86a8SGonglei uint32_t queue_index, Error **errp); 1589e4f86a8SGonglei int (*close_session)(CryptoDevBackend *backend, 1599e4f86a8SGonglei uint64_t session_id, 1609e4f86a8SGonglei uint32_t queue_index, Error **errp); 1619e4f86a8SGonglei int (*do_sym_op)(CryptoDevBackend *backend, 1629e4f86a8SGonglei CryptoDevBackendSymOpInfo *op_info, 1639e4f86a8SGonglei uint32_t queue_index, Error **errp); 164d0ee7a13SGonglei } CryptoDevBackendClass; 165d0ee7a13SGonglei 1665da73dabSGonglei typedef enum CryptoDevBackendOptionsType { 1675da73dabSGonglei CRYPTODEV_BACKEND_TYPE_NONE = 0, 1685da73dabSGonglei CRYPTODEV_BACKEND_TYPE_BUILTIN = 1, 1695da73dabSGonglei CRYPTODEV_BACKEND_TYPE_VHOST_USER = 2, 1705da73dabSGonglei CRYPTODEV_BACKEND_TYPE__MAX, 1715da73dabSGonglei } CryptoDevBackendOptionsType; 172d0ee7a13SGonglei 173d0ee7a13SGonglei struct CryptoDevBackendClient { 1745da73dabSGonglei CryptoDevBackendOptionsType type; 175d0ee7a13SGonglei char *model; 176d0ee7a13SGonglei char *name; 177d0ee7a13SGonglei char *info_str; 178d0ee7a13SGonglei unsigned int queue_index; 1795da73dabSGonglei int vring_enable; 180d0ee7a13SGonglei QTAILQ_ENTRY(CryptoDevBackendClient) next; 181d0ee7a13SGonglei }; 182d0ee7a13SGonglei 183d0ee7a13SGonglei struct CryptoDevBackendPeers { 184d0ee7a13SGonglei CryptoDevBackendClient *ccs[MAX_CRYPTO_QUEUE_NUM]; 185d0ee7a13SGonglei uint32_t queues; 186d0ee7a13SGonglei }; 187d0ee7a13SGonglei 188d0ee7a13SGonglei struct CryptoDevBackendConf { 189d0ee7a13SGonglei CryptoDevBackendPeers peers; 190d0ee7a13SGonglei 191d0ee7a13SGonglei /* Supported service mask */ 192d0ee7a13SGonglei uint32_t crypto_services; 193d0ee7a13SGonglei 194d0ee7a13SGonglei /* Detailed algorithms mask */ 195d0ee7a13SGonglei uint32_t cipher_algo_l; 196d0ee7a13SGonglei uint32_t cipher_algo_h; 197d0ee7a13SGonglei uint32_t hash_algo; 198d0ee7a13SGonglei uint32_t mac_algo_l; 199d0ee7a13SGonglei uint32_t mac_algo_h; 200d0ee7a13SGonglei uint32_t aead_algo; 201d0ee7a13SGonglei /* Maximum length of cipher key */ 202d0ee7a13SGonglei uint32_t max_cipher_key_len; 203d0ee7a13SGonglei /* Maximum length of authenticated key */ 204d0ee7a13SGonglei uint32_t max_auth_key_len; 205d0ee7a13SGonglei /* Maximum size of each crypto request's content */ 206d0ee7a13SGonglei uint64_t max_size; 207d0ee7a13SGonglei }; 208d0ee7a13SGonglei 209d0ee7a13SGonglei struct CryptoDevBackend { 210d0ee7a13SGonglei Object parent_obj; 211d0ee7a13SGonglei 212d0ee7a13SGonglei bool ready; 21346fd1705SGonglei /* Tag the cryptodev backend is used by virtio-crypto or not */ 21446fd1705SGonglei bool is_used; 215d0ee7a13SGonglei CryptoDevBackendConf conf; 216d0ee7a13SGonglei }; 217d0ee7a13SGonglei 218d0ee7a13SGonglei /** 219d0ee7a13SGonglei * cryptodev_backend_new_client: 220d0ee7a13SGonglei * @model: the cryptodev backend model 221d0ee7a13SGonglei * @name: the cryptodev backend name, can be NULL 222d0ee7a13SGonglei * 223d0ee7a13SGonglei * Creates a new cryptodev backend client object 224d0ee7a13SGonglei * with the @name in the model @model. 225d0ee7a13SGonglei * 226d0ee7a13SGonglei * The returned object must be released with 227d0ee7a13SGonglei * cryptodev_backend_free_client() when no 228d0ee7a13SGonglei * longer required 229d0ee7a13SGonglei * 230d0ee7a13SGonglei * Returns: a new cryptodev backend client object 231d0ee7a13SGonglei */ 232d0ee7a13SGonglei CryptoDevBackendClient * 233d0ee7a13SGonglei cryptodev_backend_new_client(const char *model, 234d0ee7a13SGonglei const char *name); 235d0ee7a13SGonglei /** 236d0ee7a13SGonglei * cryptodev_backend_free_client: 237d0ee7a13SGonglei * @cc: the cryptodev backend client object 238d0ee7a13SGonglei * 239d0ee7a13SGonglei * Release the memory associated with @cc that 240d0ee7a13SGonglei * was previously allocated by cryptodev_backend_new_client() 241d0ee7a13SGonglei */ 242d0ee7a13SGonglei void cryptodev_backend_free_client( 243d0ee7a13SGonglei CryptoDevBackendClient *cc); 244d0ee7a13SGonglei 245d0ee7a13SGonglei /** 246d0ee7a13SGonglei * cryptodev_backend_cleanup: 247d0ee7a13SGonglei * @backend: the cryptodev backend object 248d0ee7a13SGonglei * @errp: pointer to a NULL-initialized error object 249d0ee7a13SGonglei * 250d0ee7a13SGonglei * Clean the resouce associated with @backend that realizaed 251d0ee7a13SGonglei * by the specific backend's init() callback 252d0ee7a13SGonglei */ 253d0ee7a13SGonglei void cryptodev_backend_cleanup( 254d0ee7a13SGonglei CryptoDevBackend *backend, 255d0ee7a13SGonglei Error **errp); 256d0ee7a13SGonglei 2579e4f86a8SGonglei /** 2589e4f86a8SGonglei * cryptodev_backend_sym_create_session: 2599e4f86a8SGonglei * @backend: the cryptodev backend object 2609e4f86a8SGonglei * @sess_info: parameters needed by session creating 2619e4f86a8SGonglei * @queue_index: queue index of cryptodev backend client 2629e4f86a8SGonglei * @errp: pointer to a NULL-initialized error object 2639e4f86a8SGonglei * 2649e4f86a8SGonglei * Create a session for symmetric algorithms 2659e4f86a8SGonglei * 2669e4f86a8SGonglei * Returns: session id on success, or -1 on error 2679e4f86a8SGonglei */ 2689e4f86a8SGonglei int64_t cryptodev_backend_sym_create_session( 2699e4f86a8SGonglei CryptoDevBackend *backend, 2709e4f86a8SGonglei CryptoDevBackendSymSessionInfo *sess_info, 2719e4f86a8SGonglei uint32_t queue_index, Error **errp); 2729e4f86a8SGonglei 2739e4f86a8SGonglei /** 2749e4f86a8SGonglei * cryptodev_backend_sym_close_session: 2759e4f86a8SGonglei * @backend: the cryptodev backend object 2769e4f86a8SGonglei * @session_id: the session id 2779e4f86a8SGonglei * @queue_index: queue index of cryptodev backend client 2789e4f86a8SGonglei * @errp: pointer to a NULL-initialized error object 2799e4f86a8SGonglei * 2809e4f86a8SGonglei * Close a session for symmetric algorithms which was previously 2819e4f86a8SGonglei * created by cryptodev_backend_sym_create_session() 2829e4f86a8SGonglei * 2839e4f86a8SGonglei * Returns: 0 on success, or Negative on error 2849e4f86a8SGonglei */ 2859e4f86a8SGonglei int cryptodev_backend_sym_close_session( 2869e4f86a8SGonglei CryptoDevBackend *backend, 2879e4f86a8SGonglei uint64_t session_id, 2889e4f86a8SGonglei uint32_t queue_index, Error **errp); 2899e4f86a8SGonglei 2909e4f86a8SGonglei /** 291d6634ac0SGonglei * cryptodev_backend_crypto_operation: 2929e4f86a8SGonglei * @backend: the cryptodev backend object 293d6634ac0SGonglei * @opaque: pointer to a VirtIOCryptoReq object 2949e4f86a8SGonglei * @queue_index: queue index of cryptodev backend client 2959e4f86a8SGonglei * @errp: pointer to a NULL-initialized error object 2969e4f86a8SGonglei * 297d6634ac0SGonglei * Do crypto operation, such as encryption and 2989e4f86a8SGonglei * decryption 2999e4f86a8SGonglei * 300d6634ac0SGonglei * Returns: VIRTIO_CRYPTO_OK on success, 301d6634ac0SGonglei * or -VIRTIO_CRYPTO_* on error 3029e4f86a8SGonglei */ 303d6634ac0SGonglei int cryptodev_backend_crypto_operation( 3049e4f86a8SGonglei CryptoDevBackend *backend, 305d6634ac0SGonglei void *opaque, 3069e4f86a8SGonglei uint32_t queue_index, Error **errp); 3079e4f86a8SGonglei 30846fd1705SGonglei /** 30946fd1705SGonglei * cryptodev_backend_set_used: 31046fd1705SGonglei * @backend: the cryptodev backend object 31146fd1705SGonglei * @used: ture or false 31246fd1705SGonglei * 31346fd1705SGonglei * Set the cryptodev backend is used by virtio-crypto or not 31446fd1705SGonglei */ 31546fd1705SGonglei void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used); 31646fd1705SGonglei 31746fd1705SGonglei /** 31846fd1705SGonglei * cryptodev_backend_is_used: 31946fd1705SGonglei * @backend: the cryptodev backend object 32046fd1705SGonglei * 32146fd1705SGonglei * Return the status that the cryptodev backend is used 32246fd1705SGonglei * by virtio-crypto or not 32346fd1705SGonglei * 32446fd1705SGonglei * Returns: true on used, or false on not used 32546fd1705SGonglei */ 32646fd1705SGonglei bool cryptodev_backend_is_used(CryptoDevBackend *backend); 32746fd1705SGonglei 3286138dbdaSGonglei /** 3296138dbdaSGonglei * cryptodev_backend_set_ready: 3306138dbdaSGonglei * @backend: the cryptodev backend object 3316138dbdaSGonglei * @ready: ture or false 3326138dbdaSGonglei * 3336138dbdaSGonglei * Set the cryptodev backend is ready or not, which is called 3346138dbdaSGonglei * by the children of the cryptodev banckend interface. 3356138dbdaSGonglei */ 3366138dbdaSGonglei void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready); 3376138dbdaSGonglei 3386138dbdaSGonglei /** 3396138dbdaSGonglei * cryptodev_backend_is_ready: 3406138dbdaSGonglei * @backend: the cryptodev backend object 3416138dbdaSGonglei * 3426138dbdaSGonglei * Return the status that the cryptodev backend is ready or not 3436138dbdaSGonglei * 3446138dbdaSGonglei * Returns: true on ready, or false on not ready 3456138dbdaSGonglei */ 3466138dbdaSGonglei bool cryptodev_backend_is_ready(CryptoDevBackend *backend); 34746fd1705SGonglei 348d0ee7a13SGonglei #endif /* CRYPTODEV_H */ 349