2 * QEMU Crypto af_alg-backend hash/hmac 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"
15 #include "qemu/sockets.h"
16 #include "qapi/error.h"
17 #include "crypto/hash.h"
18 #include "crypto/hmac.h"
23 qcrypto_afalg_hash_format_name(QCryptoHashAlgorithm alg
,
31 case QCRYPTO_HASH_ALG_MD5
:
34 case QCRYPTO_HASH_ALG_SHA1
:
37 case QCRYPTO_HASH_ALG_SHA224
:
40 case QCRYPTO_HASH_ALG_SHA256
:
43 case QCRYPTO_HASH_ALG_SHA384
:
46 case QCRYPTO_HASH_ALG_SHA512
:
49 case QCRYPTO_HASH_ALG_RIPEMD160
:
54 error_setg(errp
, "Unsupported hash algorithm %d", alg
);
59 name
= g_strdup_printf("hmac(%s)", alg_name
);
61 name
= g_strdup_printf("%s", alg_name
);
68 qcrypto_afalg_hash_hmac_ctx_new(QCryptoHashAlgorithm alg
,
69 const uint8_t *key
, size_t nkey
,
70 bool is_hmac
, Error
**errp
)
75 name
= qcrypto_afalg_hash_format_name(alg
, is_hmac
, errp
);
80 afalg
= qcrypto_afalg_comm_alloc(AFALG_TYPE_HASH
, name
, errp
);
88 /* HMAC needs setkey */
90 if (setsockopt(afalg
->tfmfd
, SOL_ALG
, ALG_SET_KEY
,
92 error_setg_errno(errp
, errno
, "Set hmac key failed");
93 qcrypto_afalg_comm_free(afalg
);
101 static QCryptoAFAlg
*
102 qcrypto_afalg_hash_ctx_new(QCryptoHashAlgorithm alg
,
105 return qcrypto_afalg_hash_hmac_ctx_new(alg
, NULL
, 0, false, errp
);
109 qcrypto_afalg_hmac_ctx_new(QCryptoHashAlgorithm alg
,
110 const uint8_t *key
, size_t nkey
,
113 return qcrypto_afalg_hash_hmac_ctx_new(alg
, key
, nkey
, true, errp
);
117 qcrypto_afalg_hash_hmac_bytesv(QCryptoAFAlg
*hmac
,
118 QCryptoHashAlgorithm alg
,
119 const struct iovec
*iov
,
120 size_t niov
, uint8_t **result
,
127 bool is_hmac
= (hmac
!= NULL
) ? true : false;
128 const int expect_len
= qcrypto_hash_digest_len(alg
);
130 if (*resultlen
== 0) {
131 *resultlen
= expect_len
;
132 *result
= g_new0(uint8_t, *resultlen
);
133 } else if (*resultlen
!= expect_len
) {
135 "Result buffer size %zu is not match hash %d",
136 *resultlen
, expect_len
);
143 afalg
= qcrypto_afalg_hash_ctx_new(alg
, errp
);
149 /* send data to kernel's crypto core */
150 ret
= iov_send_recv(afalg
->opfd
, iov
, niov
,
151 0, iov_size(iov
, niov
), true);
153 error_setg_errno(errp
, errno
, "Send data to afalg-core failed");
157 /* hash && get result */
158 outv
.iov_base
= *result
;
159 outv
.iov_len
= *resultlen
;
160 ret
= iov_send_recv(afalg
->opfd
, &outv
, 1,
161 0, iov_size(&outv
, 1), false);
163 error_setg_errno(errp
, errno
, "Recv result from afalg-core failed");
170 qcrypto_afalg_comm_free(afalg
);
176 qcrypto_afalg_hash_bytesv(QCryptoHashAlgorithm alg
,
177 const struct iovec
*iov
,
178 size_t niov
, uint8_t **result
,
182 return qcrypto_afalg_hash_hmac_bytesv(NULL
, alg
, iov
, niov
, result
,
187 qcrypto_afalg_hmac_bytesv(QCryptoHmac
*hmac
,
188 const struct iovec
*iov
,
189 size_t niov
, uint8_t **result
,
193 return qcrypto_afalg_hash_hmac_bytesv(hmac
->opaque
, hmac
->alg
,
194 iov
, niov
, result
, resultlen
,
198 static void qcrypto_afalg_hmac_ctx_free(QCryptoHmac
*hmac
)
202 afalg
= hmac
->opaque
;
203 qcrypto_afalg_comm_free(afalg
);
206 QCryptoHashDriver qcrypto_hash_afalg_driver
= {
207 .hash_bytesv
= qcrypto_afalg_hash_bytesv
,
210 QCryptoHmacDriver qcrypto_hmac_afalg_driver
= {
211 .hmac_bytesv
= qcrypto_afalg_hmac_bytesv
,
212 .hmac_free
= qcrypto_afalg_hmac_ctx_free
,