mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00

Introduce the SM3 cryptographic hash algorithm (GB/T 32905-2016). SM3 (GB/T 32905-2016) is a cryptographic standard issued by the Organization of State Commercial Cryptography Administration (OSCCA) as an authorized cryptographic algorithm for use within China. Detect the SM3 cryptographic hash algorithm and enable the feature silently if it is available. Signed-off-by: cheliequan <cheliequan@inspur.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
153 lines
3.9 KiB
C
153 lines
3.9 KiB
C
/*
|
|
* QEMU Crypto hmac algorithms (based on libgcrypt)
|
|
*
|
|
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
|
|
*
|
|
* Authors:
|
|
* Longpeng(Mike) <longpeng2@huawei.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
|
* (at your option) any later version. See the COPYING file in the
|
|
* top-level directory.
|
|
*
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "crypto/hmac.h"
|
|
#include "hmacpriv.h"
|
|
#include <gcrypt.h>
|
|
|
|
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
|
|
[QCRYPTO_HASH_ALGO_MD5] = GCRY_MAC_HMAC_MD5,
|
|
[QCRYPTO_HASH_ALGO_SHA1] = GCRY_MAC_HMAC_SHA1,
|
|
[QCRYPTO_HASH_ALGO_SHA224] = GCRY_MAC_HMAC_SHA224,
|
|
[QCRYPTO_HASH_ALGO_SHA256] = GCRY_MAC_HMAC_SHA256,
|
|
[QCRYPTO_HASH_ALGO_SHA384] = GCRY_MAC_HMAC_SHA384,
|
|
[QCRYPTO_HASH_ALGO_SHA512] = GCRY_MAC_HMAC_SHA512,
|
|
[QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MAC_HMAC_RMD160,
|
|
#ifdef CONFIG_CRYPTO_SM3
|
|
[QCRYPTO_HASH_ALGO_SM3] = GCRY_MAC_HMAC_SM3,
|
|
#endif
|
|
};
|
|
|
|
typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
|
|
struct QCryptoHmacGcrypt {
|
|
gcry_mac_hd_t handle;
|
|
};
|
|
|
|
bool qcrypto_hmac_supports(QCryptoHashAlgo alg)
|
|
{
|
|
if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
|
|
qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void *qcrypto_hmac_ctx_new(QCryptoHashAlgo alg,
|
|
const uint8_t *key, size_t nkey,
|
|
Error **errp)
|
|
{
|
|
QCryptoHmacGcrypt *ctx;
|
|
gcry_error_t err;
|
|
|
|
if (!qcrypto_hmac_supports(alg)) {
|
|
error_setg(errp, "Unsupported hmac algorithm %s",
|
|
QCryptoHashAlgo_str(alg));
|
|
return NULL;
|
|
}
|
|
|
|
ctx = g_new0(QCryptoHmacGcrypt, 1);
|
|
|
|
err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
|
|
GCRY_MAC_FLAG_SECURE, NULL);
|
|
if (err != 0) {
|
|
error_setg(errp, "Cannot initialize hmac: %s",
|
|
gcry_strerror(err));
|
|
goto error;
|
|
}
|
|
|
|
err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey);
|
|
if (err != 0) {
|
|
error_setg(errp, "Cannot set key: %s",
|
|
gcry_strerror(err));
|
|
gcry_mac_close(ctx->handle);
|
|
goto error;
|
|
}
|
|
|
|
return ctx;
|
|
|
|
error:
|
|
g_free(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
qcrypto_gcrypt_hmac_ctx_free(QCryptoHmac *hmac)
|
|
{
|
|
QCryptoHmacGcrypt *ctx;
|
|
|
|
ctx = hmac->opaque;
|
|
gcry_mac_close(ctx->handle);
|
|
|
|
g_free(ctx);
|
|
}
|
|
|
|
static int
|
|
qcrypto_gcrypt_hmac_bytesv(QCryptoHmac *hmac,
|
|
const struct iovec *iov,
|
|
size_t niov,
|
|
uint8_t **result,
|
|
size_t *resultlen,
|
|
Error **errp)
|
|
{
|
|
QCryptoHmacGcrypt *ctx;
|
|
gcry_error_t err;
|
|
uint32_t ret;
|
|
int i;
|
|
|
|
ctx = hmac->opaque;
|
|
|
|
for (i = 0; i < niov; i++) {
|
|
gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len);
|
|
}
|
|
|
|
ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]);
|
|
if (ret <= 0) {
|
|
error_setg(errp, "Unable to get hmac length: %s",
|
|
gcry_strerror(ret));
|
|
return -1;
|
|
}
|
|
|
|
if (*resultlen == 0) {
|
|
*resultlen = ret;
|
|
*result = g_new0(uint8_t, *resultlen);
|
|
} else if (*resultlen != ret) {
|
|
error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
|
|
*resultlen, ret);
|
|
return -1;
|
|
}
|
|
|
|
err = gcry_mac_read(ctx->handle, *result, resultlen);
|
|
if (err != 0) {
|
|
error_setg(errp, "Cannot get result: %s",
|
|
gcry_strerror(err));
|
|
return -1;
|
|
}
|
|
|
|
err = gcry_mac_reset(ctx->handle);
|
|
if (err != 0) {
|
|
error_setg(errp, "Cannot reset hmac context: %s",
|
|
gcry_strerror(err));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
|
|
.hmac_bytesv = qcrypto_gcrypt_hmac_bytesv,
|
|
.hmac_free = qcrypto_gcrypt_hmac_ctx_free,
|
|
};
|