2 * QEMU Crypto af_alg-backend cipher support
4 * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
7 * Longpeng(Mike) <longpeng2@huawei.com>
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
,