2 * QEMU Crypto af_alg-backend cipher support
4 * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
9 * This work is licensed under the terms of the GNU GPL, version 2 or
10 * (at your option) any later version. See the COPYING file in the
11 * top-level directory.
13 #include "qemu/osdep.h"
14 #include "qemu/sockets.h"
15 #include "qemu-common.h"
16 #include "qapi/error.h"
17 #include "crypto/cipher.h"
18 #include "cipherpriv.h"
22 qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg,
23 QCryptoCipherMode mode,
28 const char *mode_name;
31 case QCRYPTO_CIPHER_ALG_AES_128:
32 case QCRYPTO_CIPHER_ALG_AES_192:
33 case QCRYPTO_CIPHER_ALG_AES_256:
36 case QCRYPTO_CIPHER_ALG_CAST5_128:
39 case QCRYPTO_CIPHER_ALG_SERPENT_128:
40 case QCRYPTO_CIPHER_ALG_SERPENT_192:
41 case QCRYPTO_CIPHER_ALG_SERPENT_256:
44 case QCRYPTO_CIPHER_ALG_TWOFISH_128:
45 case QCRYPTO_CIPHER_ALG_TWOFISH_192:
46 case QCRYPTO_CIPHER_ALG_TWOFISH_256:
51 error_setg(errp, "Unsupported cipher algorithm %d", alg);
55 mode_name = QCryptoCipherMode_str(mode);
56 name = g_strdup_printf("%s(%s)", mode_name, alg_name);
62 qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg,
63 QCryptoCipherMode mode,
65 size_t nkey, Error **errp)
71 name = qcrypto_afalg_cipher_format_name(alg, mode, errp);
76 afalg = qcrypto_afalg_comm_alloc(AFALG_TYPE_CIPHER, name, errp);
85 if (qemu_setsockopt(afalg->tfmfd, SOL_ALG, ALG_SET_KEY, key,
87 error_setg_errno(errp, errno, "Set key failed");
88 qcrypto_afalg_comm_free(afalg);
92 /* prepare msg header */
93 afalg->msg = g_new0(struct msghdr, 1);
94 afalg->msg->msg_controllen += CMSG_SPACE(ALG_OPTYPE_LEN);
95 expect_niv = qcrypto_cipher_get_iv_len(alg, mode);
97 afalg->msg->msg_controllen += CMSG_SPACE(ALG_MSGIV_LEN(expect_niv));
99 afalg->msg->msg_control = g_new0(uint8_t, afalg->msg->msg_controllen);
101 /* We use 1st msghdr for crypto-info and 2nd msghdr for IV-info */
102 afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
103 afalg->cmsg->cmsg_type = ALG_SET_OP;
104 afalg->cmsg->cmsg_len = CMSG_SPACE(ALG_OPTYPE_LEN);
106 afalg->cmsg = CMSG_NXTHDR(afalg->msg, afalg->cmsg);
107 afalg->cmsg->cmsg_type = ALG_SET_IV;
108 afalg->cmsg->cmsg_len = CMSG_SPACE(ALG_MSGIV_LEN(expect_niv));
110 afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
116 qcrypto_afalg_cipher_setiv(QCryptoCipher *cipher,
118 size_t niv, Error **errp)
120 struct af_alg_iv *alg_iv;
122 QCryptoAFAlg *afalg = cipher->opaque;
124 expect_niv = qcrypto_cipher_get_iv_len(cipher->alg, cipher->mode);
125 if (niv != expect_niv) {
126 error_setg(errp, "Set IV len(%zu) not match expected(%zu)",
131 /* move ->cmsg to next msghdr, for IV-info */
132 afalg->cmsg = CMSG_NXTHDR(afalg->msg, afalg->cmsg);
134 /* build setiv msg */
135 afalg->cmsg->cmsg_level = SOL_ALG;
136 alg_iv = (struct af_alg_iv *)CMSG_DATA(afalg->cmsg);
138 memcpy(alg_iv->iv, iv, niv);
144 qcrypto_afalg_cipher_op(QCryptoAFAlg *afalg,
145 const void *in, void *out,
146 size_t len, bool do_encrypt,
149 uint32_t *type = NULL;
151 size_t ret, rlen, done = 0;
152 uint32_t origin_controllen;
154 origin_controllen = afalg->msg->msg_controllen;
155 /* movev ->cmsg to first header, for crypto-info */
156 afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
158 /* build encrypt msg */
159 afalg->cmsg->cmsg_level = SOL_ALG;
160 afalg->msg->msg_iov = &iov;
161 afalg->msg->msg_iovlen = 1;
162 type = (uint32_t *)CMSG_DATA(afalg->cmsg);
164 *type = ALG_OP_ENCRYPT;
166 *type = ALG_OP_DECRYPT;
170 iov.iov_base = (void *)in + done;
171 iov.iov_len = len - done;
173 /* send info to AF_ALG core */
174 ret = sendmsg(afalg->opfd, afalg->msg, 0);
176 error_setg_errno(errp, errno, "Send data to AF_ALG core failed");
180 /* encrypto && get result */
181 rlen = read(afalg->opfd, out, ret);
183 error_setg_errno(errp, errno, "Get result from AF_ALG core failed");
188 /* do not update IV for following chunks */
189 afalg->msg->msg_controllen = 0;
191 } while (done < len);
193 afalg->msg->msg_controllen = origin_controllen;
199 qcrypto_afalg_cipher_encrypt(QCryptoCipher *cipher,
200 const void *in, void *out,
201 size_t len, Error **errp)
203 return qcrypto_afalg_cipher_op(cipher->opaque, in, out,
208 qcrypto_afalg_cipher_decrypt(QCryptoCipher *cipher,
209 const void *in, void *out,
210 size_t len, Error **errp)
212 return qcrypto_afalg_cipher_op(cipher->opaque, in, out,
216 static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher)
218 qcrypto_afalg_comm_free(cipher->opaque);
221 struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = {
222 .cipher_encrypt = qcrypto_afalg_cipher_encrypt,
223 .cipher_decrypt = qcrypto_afalg_cipher_decrypt,
224 .cipher_setiv = qcrypto_afalg_cipher_setiv,
225 .cipher_free = qcrypto_afalg_comm_ctx_free,