2 * QEMU Crypto af_alg-backend hash/hmac support
4 * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
5 * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
8 * Longpeng(Mike) <longpeng2@huawei.com>
10 * This work is licensed under the terms of the GNU GPL, version 2 or
11 * (at your option) any later version. See the COPYING file in the
12 * top-level directory.
14 #include "qemu/osdep.h"
16 #include "qemu/sockets.h"
17 #include "qapi/error.h"
18 #include "crypto/hash.h"
19 #include "crypto/hmac.h"
24 qcrypto_afalg_hash_format_name(QCryptoHashAlgo alg
,
32 case QCRYPTO_HASH_ALGO_MD5
:
35 case QCRYPTO_HASH_ALGO_SHA1
:
38 case QCRYPTO_HASH_ALGO_SHA224
:
41 case QCRYPTO_HASH_ALGO_SHA256
:
44 case QCRYPTO_HASH_ALGO_SHA384
:
47 case QCRYPTO_HASH_ALGO_SHA512
:
50 case QCRYPTO_HASH_ALGO_RIPEMD160
:
55 error_setg(errp
, "Unsupported hash algorithm %d", alg
);
60 name
= g_strdup_printf("hmac(%s)", alg_name
);
62 name
= g_strdup_printf("%s", alg_name
);
68 static QCryptoAFAlgo
*
69 qcrypto_afalg_hash_hmac_ctx_new(QCryptoHashAlgo alg
,
70 const uint8_t *key
, size_t nkey
,
71 bool is_hmac
, Error
**errp
)
76 name
= qcrypto_afalg_hash_format_name(alg
, is_hmac
, errp
);
81 afalg
= qcrypto_afalg_comm_alloc(AFALG_TYPE_HASH
, name
, errp
);
89 /* HMAC needs setkey */
91 if (setsockopt(afalg
->tfmfd
, SOL_ALG
, ALG_SET_KEY
,
93 error_setg_errno(errp
, errno
, "Set hmac key failed");
94 qcrypto_afalg_comm_free(afalg
);
102 static QCryptoAFAlgo
*
103 qcrypto_afalg_hash_ctx_new(QCryptoHashAlgo alg
,
106 return qcrypto_afalg_hash_hmac_ctx_new(alg
, NULL
, 0, false, errp
);
110 qcrypto_afalg_hmac_ctx_new(QCryptoHashAlgo alg
,
111 const uint8_t *key
, size_t nkey
,
114 return qcrypto_afalg_hash_hmac_ctx_new(alg
, key
, nkey
, true, errp
);
118 QCryptoHash
*qcrypto_afalg_hash_new(QCryptoHashAlgo alg
, Error
**errp
)
120 /* Check if hash algorithm is supported */
121 char *alg_name
= qcrypto_afalg_hash_format_name(alg
, false, NULL
);
124 if (alg_name
== NULL
) {
125 error_setg(errp
, "Unknown hash algorithm %d", alg
);
131 hash
= g_new(QCryptoHash
, 1);
133 hash
->opaque
= qcrypto_afalg_hash_ctx_new(alg
, errp
);
143 void qcrypto_afalg_hash_free(QCryptoHash
*hash
)
145 QCryptoAFAlg
*ctx
= hash
->opaque
;
148 qcrypto_afalg_comm_free(ctx
);
155 * Send data to the kernel's crypto core.
157 * The more_data parameter is used to notify the crypto engine
158 * that this is an "update" operation, and that more data will
159 * be provided to calculate the final hash.
162 int qcrypto_afalg_send_to_kernel(QCryptoAFAlg
*afalg
,
163 const struct iovec
*iov
,
169 int flags
= (more_data
? MSG_MORE
: 0);
171 /* send data to kernel's crypto core */
172 ret
= iov_send_recv_with_flags(afalg
->opfd
, flags
, iov
, niov
,
173 0, iov_size(iov
, niov
), true);
175 error_setg_errno(errp
, errno
, "Send data to afalg-core failed");
178 /* No error, so return 0 */
186 int qcrypto_afalg_recv_from_kernel(QCryptoAFAlg
*afalg
,
194 const int expected_len
= qcrypto_hash_digest_len(alg
);
196 if (*result_len
== 0) {
197 *result_len
= expected_len
;
198 *result
= g_new0(uint8_t, *result_len
);
199 } else if (*result_len
!= expected_len
) {
201 "Result buffer size %zu is not match hash %d",
202 *result_len
, expected_len
);
206 /* hash && get result */
207 outv
.iov_base
= *result
;
208 outv
.iov_len
= *result_len
;
209 ret
= iov_send_recv(afalg
->opfd
, &outv
, 1,
210 0, iov_size(&outv
, 1), false);
212 error_setg_errno(errp
, errno
, "Recv result from afalg-core failed");
220 int qcrypto_afalg_hash_update(QCryptoHash
*hash
,
221 const struct iovec
*iov
,
225 return qcrypto_afalg_send_to_kernel((QCryptoAFAlg
*) hash
->opaque
,
226 iov
, niov
, true, errp
);
230 int qcrypto_afalg_hash_finalize(QCryptoHash
*hash
,
235 return qcrypto_afalg_recv_from_kernel((QCryptoAFAlg
*) hash
->opaque
,
236 hash
->alg
, result
, result_len
, errp
);
240 qcrypto_afalg_hash_hmac_bytesv(QCryptoAFAlgo
*hmac
,
242 const struct iovec
*iov
,
243 size_t niov
, uint8_t **result
,
249 ret
= qcrypto_afalg_send_to_kernel(hmac
, iov
, niov
, false, errp
);
251 ret
= qcrypto_afalg_recv_from_kernel(hmac
, alg
, result
,
259 qcrypto_afalg_hmac_bytesv(QCryptoHmac
*hmac
,
260 const struct iovec
*iov
,
261 size_t niov
, uint8_t **result
,
265 return qcrypto_afalg_hash_hmac_bytesv(hmac
->opaque
, hmac
->alg
,
266 iov
, niov
, result
, resultlen
,
270 static void qcrypto_afalg_hmac_ctx_free(QCryptoHmac
*hmac
)
272 QCryptoAFAlgo
*afalg
;
274 afalg
= hmac
->opaque
;
275 qcrypto_afalg_comm_free(afalg
);
278 QCryptoHashDriver qcrypto_hash_afalg_driver
= {
279 .hash_new
= qcrypto_afalg_hash_new
,
280 .hash_free
= qcrypto_afalg_hash_free
,
281 .hash_update
= qcrypto_afalg_hash_update
,
282 .hash_finalize
= qcrypto_afalg_hash_finalize
285 QCryptoHmacDriver qcrypto_hmac_afalg_driver
= {
286 .hmac_bytesv
= qcrypto_afalg_hmac_bytesv
,
287 .hmac_free
= qcrypto_afalg_hmac_ctx_free
,