d078da86d6
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>
186 lines
5.9 KiB
C
186 lines
5.9 KiB
C
/*
|
|
* QEMU Crypto hmac algorithms (based on nettle)
|
|
*
|
|
* 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 <nettle/hmac.h>
|
|
|
|
typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
|
|
size_t key_length,
|
|
const uint8_t *key);
|
|
|
|
typedef void (*qcrypto_nettle_hmac_update)(void *ctx,
|
|
size_t length,
|
|
const uint8_t *data);
|
|
|
|
typedef void (*qcrypto_nettle_hmac_digest)(void *ctx,
|
|
size_t length,
|
|
uint8_t *digest);
|
|
|
|
typedef struct QCryptoHmacNettle QCryptoHmacNettle;
|
|
struct QCryptoHmacNettle {
|
|
union qcrypto_nettle_hmac_ctx {
|
|
struct hmac_md5_ctx md5_ctx;
|
|
struct hmac_sha1_ctx sha1_ctx;
|
|
struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */
|
|
struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */
|
|
struct hmac_ripemd160_ctx ripemd160_ctx;
|
|
#ifdef CONFIG_CRYPTO_SM3
|
|
struct hmac_sm3_ctx ctx;
|
|
#endif
|
|
} u;
|
|
};
|
|
|
|
struct qcrypto_nettle_hmac_alg {
|
|
qcrypto_nettle_hmac_setkey setkey;
|
|
qcrypto_nettle_hmac_update update;
|
|
qcrypto_nettle_hmac_digest digest;
|
|
size_t len;
|
|
} qcrypto_hmac_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
|
|
[QCRYPTO_HASH_ALGO_MD5] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_md5_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_md5_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_md5_digest,
|
|
.len = MD5_DIGEST_SIZE,
|
|
},
|
|
[QCRYPTO_HASH_ALGO_SHA1] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha1_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_sha1_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha1_digest,
|
|
.len = SHA1_DIGEST_SIZE,
|
|
},
|
|
[QCRYPTO_HASH_ALGO_SHA224] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha224_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_sha224_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha224_digest,
|
|
.len = SHA224_DIGEST_SIZE,
|
|
},
|
|
[QCRYPTO_HASH_ALGO_SHA256] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha256_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_sha256_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha256_digest,
|
|
.len = SHA256_DIGEST_SIZE,
|
|
},
|
|
[QCRYPTO_HASH_ALGO_SHA384] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha384_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_sha384_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha384_digest,
|
|
.len = SHA384_DIGEST_SIZE,
|
|
},
|
|
[QCRYPTO_HASH_ALGO_SHA512] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sha512_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_sha512_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sha512_digest,
|
|
.len = SHA512_DIGEST_SIZE,
|
|
},
|
|
[QCRYPTO_HASH_ALGO_RIPEMD160] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_ripemd160_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_ripemd160_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest,
|
|
.len = RIPEMD160_DIGEST_SIZE,
|
|
},
|
|
#ifdef CONFIG_CRYPTO_SM3
|
|
[QCRYPTO_HASH_ALGO_SM3] = {
|
|
.setkey = (qcrypto_nettle_hmac_setkey)hmac_sm3_set_key,
|
|
.update = (qcrypto_nettle_hmac_update)hmac_sm3_update,
|
|
.digest = (qcrypto_nettle_hmac_digest)hmac_sm3_digest,
|
|
.len = SM3_DIGEST_SIZE,
|
|
},
|
|
#endif
|
|
};
|
|
|
|
bool qcrypto_hmac_supports(QCryptoHashAlgo alg)
|
|
{
|
|
if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
|
|
qcrypto_hmac_alg_map[alg].setkey != NULL) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void *qcrypto_hmac_ctx_new(QCryptoHashAlgo alg,
|
|
const uint8_t *key, size_t nkey,
|
|
Error **errp)
|
|
{
|
|
QCryptoHmacNettle *ctx;
|
|
|
|
if (!qcrypto_hmac_supports(alg)) {
|
|
error_setg(errp, "Unsupported hmac algorithm %s",
|
|
QCryptoHashAlgo_str(alg));
|
|
return NULL;
|
|
}
|
|
|
|
ctx = g_new0(QCryptoHmacNettle, 1);
|
|
|
|
qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
|
|
|
|
return ctx;
|
|
}
|
|
|
|
static void
|
|
qcrypto_nettle_hmac_ctx_free(QCryptoHmac *hmac)
|
|
{
|
|
QCryptoHmacNettle *ctx;
|
|
|
|
ctx = hmac->opaque;
|
|
g_free(ctx);
|
|
}
|
|
|
|
static int
|
|
qcrypto_nettle_hmac_bytesv(QCryptoHmac *hmac,
|
|
const struct iovec *iov,
|
|
size_t niov,
|
|
uint8_t **result,
|
|
size_t *resultlen,
|
|
Error **errp)
|
|
{
|
|
QCryptoHmacNettle *ctx;
|
|
size_t i;
|
|
|
|
ctx = (QCryptoHmacNettle *)hmac->opaque;
|
|
|
|
for (i = 0; i < niov; ++i) {
|
|
size_t len = iov[i].iov_len;
|
|
uint8_t *base = iov[i].iov_base;
|
|
while (len) {
|
|
size_t shortlen = MIN(len, UINT_MAX);
|
|
qcrypto_hmac_alg_map[hmac->alg].update(&ctx->u, len, base);
|
|
len -= shortlen;
|
|
base += len;
|
|
}
|
|
}
|
|
|
|
if (*resultlen == 0) {
|
|
*resultlen = qcrypto_hmac_alg_map[hmac->alg].len;
|
|
*result = g_new0(uint8_t, *resultlen);
|
|
} else if (*resultlen != qcrypto_hmac_alg_map[hmac->alg].len) {
|
|
error_setg(errp,
|
|
"Result buffer size %zu is smaller than hash %zu",
|
|
*resultlen, qcrypto_hmac_alg_map[hmac->alg].len);
|
|
return -1;
|
|
}
|
|
|
|
qcrypto_hmac_alg_map[hmac->alg].digest(&ctx->u, *resultlen, *result);
|
|
|
|
return 0;
|
|
}
|
|
|
|
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
|
|
.hmac_bytesv = qcrypto_nettle_hmac_bytesv,
|
|
.hmac_free = qcrypto_nettle_hmac_ctx_free,
|
|
};
|