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 "qapi/error.h"
16 #include "crypto/cipher.h"
17 #include "cipherpriv.h"
21 qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg
,
22 QCryptoCipherMode mode
,
27 const char *mode_name
;
30 case QCRYPTO_CIPHER_ALG_AES_128
:
31 case QCRYPTO_CIPHER_ALG_AES_192
:
32 case QCRYPTO_CIPHER_ALG_AES_256
:
35 case QCRYPTO_CIPHER_ALG_CAST5_128
:
38 case QCRYPTO_CIPHER_ALG_SERPENT_128
:
39 case QCRYPTO_CIPHER_ALG_SERPENT_192
:
40 case QCRYPTO_CIPHER_ALG_SERPENT_256
:
43 case QCRYPTO_CIPHER_ALG_TWOFISH_128
:
44 case QCRYPTO_CIPHER_ALG_TWOFISH_192
:
45 case QCRYPTO_CIPHER_ALG_TWOFISH_256
:
50 error_setg(errp
, "Unsupported cipher algorithm %d", alg
);
54 mode_name
= QCryptoCipherMode_str(mode
);
55 name
= g_strdup_printf("%s(%s)", mode_name
, alg_name
);
60 static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver
;
63 qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg
,
64 QCryptoCipherMode mode
,
66 size_t nkey
, Error
**errp
)
72 name
= qcrypto_afalg_cipher_format_name(alg
, mode
, errp
);
77 afalg
= qcrypto_afalg_comm_alloc(AFALG_TYPE_CIPHER
, name
, errp
);
86 if (setsockopt(afalg
->tfmfd
, SOL_ALG
, ALG_SET_KEY
, key
,
88 error_setg_errno(errp
, errno
, "Set key failed");
89 qcrypto_afalg_comm_free(afalg
);
93 /* prepare msg header */
94 afalg
->msg
= g_new0(struct msghdr
, 1);
95 afalg
->msg
->msg_controllen
+= CMSG_SPACE(ALG_OPTYPE_LEN
);
96 expect_niv
= qcrypto_cipher_get_iv_len(alg
, mode
);
98 afalg
->msg
->msg_controllen
+= CMSG_SPACE(ALG_MSGIV_LEN(expect_niv
));
100 afalg
->msg
->msg_control
= g_new0(uint8_t, afalg
->msg
->msg_controllen
);
102 /* We use 1st msghdr for crypto-info and 2nd msghdr for IV-info */
103 afalg
->cmsg
= CMSG_FIRSTHDR(afalg
->msg
);
104 afalg
->cmsg
->cmsg_type
= ALG_SET_OP
;
105 afalg
->cmsg
->cmsg_len
= CMSG_SPACE(ALG_OPTYPE_LEN
);
107 afalg
->cmsg
= CMSG_NXTHDR(afalg
->msg
, afalg
->cmsg
);
108 afalg
->cmsg
->cmsg_type
= ALG_SET_IV
;
109 afalg
->cmsg
->cmsg_len
= CMSG_SPACE(ALG_MSGIV_LEN(expect_niv
));
111 afalg
->cmsg
= CMSG_FIRSTHDR(afalg
->msg
);
113 afalg
->base
.driver
= &qcrypto_cipher_afalg_driver
;
118 qcrypto_afalg_cipher_setiv(QCryptoCipher
*cipher
,
120 size_t niv
, Error
**errp
)
122 QCryptoAFAlg
*afalg
= container_of(cipher
, QCryptoAFAlg
, base
);
123 struct af_alg_iv
*alg_iv
;
126 expect_niv
= qcrypto_cipher_get_iv_len(cipher
->alg
, cipher
->mode
);
127 if (niv
!= expect_niv
) {
128 error_setg(errp
, "Set IV len(%zu) not match expected(%zu)",
133 /* move ->cmsg to next msghdr, for IV-info */
134 afalg
->cmsg
= CMSG_NXTHDR(afalg
->msg
, afalg
->cmsg
);
136 /* build setiv msg */
137 afalg
->cmsg
->cmsg_level
= SOL_ALG
;
138 alg_iv
= (struct af_alg_iv
*)CMSG_DATA(afalg
->cmsg
);
140 memcpy(alg_iv
->iv
, iv
, niv
);
146 qcrypto_afalg_cipher_op(QCryptoAFAlg
*afalg
,
147 const void *in
, void *out
,
148 size_t len
, bool do_encrypt
,
151 uint32_t *type
= NULL
;
153 size_t ret
, rlen
, done
= 0;
154 uint32_t origin_controllen
;
156 origin_controllen
= afalg
->msg
->msg_controllen
;
157 /* movev ->cmsg to first header, for crypto-info */
158 afalg
->cmsg
= CMSG_FIRSTHDR(afalg
->msg
);
160 /* build encrypt msg */
161 afalg
->cmsg
->cmsg_level
= SOL_ALG
;
162 afalg
->msg
->msg_iov
= &iov
;
163 afalg
->msg
->msg_iovlen
= 1;
164 type
= (uint32_t *)CMSG_DATA(afalg
->cmsg
);
166 *type
= ALG_OP_ENCRYPT
;
168 *type
= ALG_OP_DECRYPT
;
172 iov
.iov_base
= (void *)in
+ done
;
173 iov
.iov_len
= len
- done
;
175 /* send info to AF_ALG core */
176 ret
= sendmsg(afalg
->opfd
, afalg
->msg
, 0);
178 error_setg_errno(errp
, errno
, "Send data to AF_ALG core failed");
182 /* encrypto && get result */
183 rlen
= read(afalg
->opfd
, out
, ret
);
185 error_setg_errno(errp
, errno
, "Get result from AF_ALG core failed");
190 /* do not update IV for following chunks */
191 afalg
->msg
->msg_controllen
= 0;
193 } while (done
< len
);
195 afalg
->msg
->msg_controllen
= origin_controllen
;
201 qcrypto_afalg_cipher_encrypt(QCryptoCipher
*cipher
,
202 const void *in
, void *out
,
203 size_t len
, Error
**errp
)
205 QCryptoAFAlg
*afalg
= container_of(cipher
, QCryptoAFAlg
, base
);
207 return qcrypto_afalg_cipher_op(afalg
, in
, out
, len
, true, errp
);
211 qcrypto_afalg_cipher_decrypt(QCryptoCipher
*cipher
,
212 const void *in
, void *out
,
213 size_t len
, Error
**errp
)
215 QCryptoAFAlg
*afalg
= container_of(cipher
, QCryptoAFAlg
, base
);
217 return qcrypto_afalg_cipher_op(afalg
, in
, out
, len
, false, errp
);
220 static void qcrypto_afalg_comm_ctx_free(QCryptoCipher
*cipher
)
222 QCryptoAFAlg
*afalg
= container_of(cipher
, QCryptoAFAlg
, base
);
224 qcrypto_afalg_comm_free(afalg
);
227 static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver
= {
228 .cipher_encrypt
= qcrypto_afalg_cipher_encrypt
,
229 .cipher_decrypt
= qcrypto_afalg_cipher_decrypt
,
230 .cipher_setiv
= qcrypto_afalg_cipher_setiv
,
231 .cipher_free
= qcrypto_afalg_comm_ctx_free
,