@@ -34,6 +34,9 @@ static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
[QCRYPTO_HASH_ALGO_SHA384] = GCRY_MD_SHA384,
[QCRYPTO_HASH_ALGO_SHA512] = GCRY_MD_SHA512,
[QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MD_RMD160,
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = GCRY_MD_SM3,
+#endif
};
gboolean qcrypto_hash_supports(QCryptoHashAlgo alg)
@@ -26,6 +26,9 @@
#include <nettle/md5.h>
#include <nettle/sha.h>
#include <nettle/ripemd160.h>
+#ifdef CONFIG_CRYPTO_SM3
+#include <nettle/sm3.h>
+#endif
typedef void (*qcrypto_nettle_init)(void *ctx);
typedef void (*qcrypto_nettle_write)(void *ctx,
@@ -43,6 +46,9 @@ union qcrypto_hash_ctx {
struct sha384_ctx sha384;
struct sha512_ctx sha512;
struct ripemd160_ctx ripemd160;
+#ifdef CONFIG_CRYPTO_SM3
+ struct sm3_ctx sm3;
+#endif
};
struct qcrypto_hash_alg {
@@ -93,6 +99,14 @@ struct qcrypto_hash_alg {
.result = (qcrypto_nettle_result)ripemd160_digest,
.len = RIPEMD160_DIGEST_SIZE,
},
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = {
+ .init = (qcrypto_nettle_init)sm3_init,
+ .write = (qcrypto_nettle_write)sm3_update,
+ .result = (qcrypto_nettle_result)sm3_digest,
+ .len = SM3_DIGEST_SIZE,
+ },
+#endif
};
gboolean qcrypto_hash_supports(QCryptoHashAlgo alg)
@@ -33,6 +33,9 @@ static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALGO__MAX] = {
[QCRYPTO_HASH_ALGO_SHA384] = QCRYPTO_HASH_DIGEST_LEN_SHA384,
[QCRYPTO_HASH_ALGO_SHA512] = QCRYPTO_HASH_DIGEST_LEN_SHA512,
[QCRYPTO_HASH_ALGO_RIPEMD160] = QCRYPTO_HASH_DIGEST_LEN_RIPEMD160,
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = QCRYPTO_HASH_DIGEST_LEN_SM3,
+#endif
};
size_t qcrypto_hash_digest_len(QCryptoHashAlgo alg)
@@ -26,6 +26,9 @@ static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
[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;
@@ -38,6 +38,9 @@ struct QCryptoHmacNettle {
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;
};
@@ -89,6 +92,14 @@ struct qcrypto_nettle_hmac_alg {
.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)
@@ -33,6 +33,9 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgo hash)
case QCRYPTO_HASH_ALGO_SHA384:
case QCRYPTO_HASH_ALGO_SHA512:
case QCRYPTO_HASH_ALGO_RIPEMD160:
+#ifdef CONFIG_CRYPTO_SM3
+ case QCRYPTO_HASH_ALGO_SM3:
+#endif
return qcrypto_hash_supports(hash);
default:
return false;
@@ -54,6 +57,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgo hash,
[QCRYPTO_HASH_ALGO_SHA384] = GCRY_MD_SHA384,
[QCRYPTO_HASH_ALGO_SHA512] = GCRY_MD_SHA512,
[QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MD_RMD160,
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = GCRY_MD_SM3,
+#endif
};
int ret;
@@ -34,6 +34,9 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgo hash)
case QCRYPTO_HASH_ALGO_SHA384:
case QCRYPTO_HASH_ALGO_SHA512:
case QCRYPTO_HASH_ALGO_RIPEMD160:
+#ifdef CONFIG_CRYPTO_SM3
+ case QCRYPTO_HASH_ALGO_SM3:
+#endif
return true;
default:
return false;
@@ -55,6 +58,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgo hash,
struct hmac_sha384_ctx sha384;
struct hmac_sha512_ctx sha512;
struct hmac_ripemd160_ctx ripemd160;
+#ifdef CONFIG_CRYPTO_SM3
+ struct hmac_sm3_ctx sm3;
+#endif
} ctx;
if (iterations > UINT_MAX) {
@@ -106,6 +112,13 @@ int qcrypto_pbkdf2(QCryptoHashAlgo hash,
PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest,
RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
break;
+#ifdef CONFIG_CRYPTO_SM3
+ case QCRYPTO_HASH_ALGO_SM3:
+ hmac_sm3_set_key(&ctx.sm3, nkey, key);
+ PBKDF2(&ctx.sm3, hmac_sm3_update, hmac_sm3_digest,
+ SM3_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
+ break;
+#endif
default:
error_setg_errno(errp, ENOSYS,
@@ -31,6 +31,7 @@
#define QCRYPTO_HASH_DIGEST_LEN_SHA384 48
#define QCRYPTO_HASH_DIGEST_LEN_SHA512 64
#define QCRYPTO_HASH_DIGEST_LEN_RIPEMD160 20
+#define QCRYPTO_HASH_DIGEST_LEN_SM3 32
/* See also "QCryptoHashAlgo" defined in qapi/crypto.json */
@@ -1760,6 +1760,7 @@ gcrypt = not_found
nettle = not_found
hogweed = not_found
crypto_sm4 = not_found
+crypto_sm3 = not_found
xts = 'none'
if get_option('nettle').enabled() and get_option('gcrypt').enabled()
@@ -1795,6 +1796,17 @@ if not gnutls_crypto.found()
}''', dependencies: gcrypt)
crypto_sm4 = not_found
endif
+ crypto_sm3 = gcrypt
+ # SM3 ALG is available in libgcrypt >= 1.9
+ if gcrypt.found() and not cc.links('''
+ #include <gcrypt.h>
+ int main(void) {
+ gcry_md_hd_t handler;
+ gcry_md_open(&handler, GCRY_MD_SM3, 0);
+ return 0;
+ }''', dependencies: gcrypt)
+ crypto_sm3 = not_found
+ endif
endif
if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
nettle = dependency('nettle', version: '>=3.4',
@@ -1815,6 +1827,31 @@ if not gnutls_crypto.found()
}''', dependencies: nettle)
crypto_sm4 = not_found
endif
+ crypto_sm3 = nettle
+ # SM3 ALG is available in nettle >= 3.8
+ if nettle.found() and not cc.links('''
+ #include <nettle/sm3.h>
+ #include <nettle/hmac.h>
+ int main(void) {
+ struct sm3_ctx ctx;
+ struct hmac_sm3_ctx hmac_ctx;
+ unsigned char data[64] = {0};
+ unsigned char output[32];
+
+ // SM3 hash function test
+ sm3_init(&ctx);
+ sm3_update(&ctx, 64, data);
+ sm3_digest(&ctx, 32, data);
+
+ // HMAC-SM3 test
+ hmac_sm3_set_key(&hmac_ctx, 32, data);
+ hmac_sm3_update(&hmac_ctx, 64, data);
+ hmac_sm3_digest(&hmac_ctx, 32, output);
+
+ return 0;
+ }''', dependencies: nettle)
+ crypto_sm3 = not_found
+ endif
endif
endif
@@ -2462,6 +2499,7 @@ config_host_data.set('CONFIG_TASN1', tasn1.found())
config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
config_host_data.set('CONFIG_NETTLE', nettle.found())
config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
+config_host_data.set('CONFIG_CRYPTO_SM3', crypto_sm3.found())
config_host_data.set('CONFIG_HOGWEED', hogweed.found())
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
@@ -4590,6 +4628,7 @@ if nettle.found()
summary_info += {' XTS': xts != 'private'}
endif
summary_info += {'SM4 ALG support': crypto_sm4}
+summary_info += {'SM3 ALG support': crypto_sm3}
summary_info += {'AF_ALG support': have_afalg}
summary_info += {'rng-none': get_option('rng_none')}
summary_info += {'Linux keyring': have_keyring}
@@ -55,11 +55,12 @@
# @sha512: SHA-512. (since 2.7)
#
# @ripemd160: RIPEMD-160. (since 2.7)
+# @sm3: SM3. (since 9.2.0)
#
# Since: 2.6
##
{ 'enum': 'QCryptoHashAlgo',
- 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']}
+ 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160', 'sm3']}
##
# @QCryptoCipherAlgo:
@@ -43,6 +43,9 @@
"63b54e4cb2d2032b393994aa263c0dbb" \
"e00a9f2fe9ef6037352232a1eec55ee7"
#define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
+#ifdef CONFIG_CRYPTO_SM3
+#define OUTPUT_SM3 "d4a97db105b477b84c4f20ec9c31a6c814e2705a0b83a5a89748d75f0ef456a1"
+#endif
#define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
#define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
@@ -55,6 +58,10 @@
"7sVe5w=="
#define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
+#ifdef CONFIG_CRYPTO_SM3
+#define OUTPUT_SM3_B64 "1Kl9sQW0d7hMTyDsnDGmyBTicFoLg6Wol0jXXw70VqE="
+#endif
+
static const char *expected_outputs[] = {
[QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5,
[QCRYPTO_HASH_ALGO_SHA1] = OUTPUT_SHA1,
@@ -63,6 +70,9 @@ static const char *expected_outputs[] = {
[QCRYPTO_HASH_ALGO_SHA384] = OUTPUT_SHA384,
[QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512,
[QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160,
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = OUTPUT_SM3,
+#endif
};
static const char *expected_outputs_b64[] = {
[QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5_B64,
@@ -72,6 +82,9 @@ static const char *expected_outputs_b64[] = {
[QCRYPTO_HASH_ALGO_SHA384] = OUTPUT_SHA384_B64,
[QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512_B64,
[QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160_B64,
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = OUTPUT_SM3_B64,
+#endif
};
static const int expected_lens[] = {
[QCRYPTO_HASH_ALGO_MD5] = 16,
@@ -81,6 +94,9 @@ static const int expected_lens[] = {
[QCRYPTO_HASH_ALGO_SHA384] = 48,
[QCRYPTO_HASH_ALGO_SHA512] = 64,
[QCRYPTO_HASH_ALGO_RIPEMD160] = 20,
+#ifdef CONFIG_CRYPTO_SM3
+ [QCRYPTO_HASH_ALGO_SM3] = 32,
+#endif
};
static const char hex[] = "0123456789abcdef";
@@ -76,6 +76,14 @@ static QCryptoHmacTestData test_data[] = {
"94964ed4c1155b62b668c241d67279e5"
"8a711676",
},
+#ifdef CONFIG_CRYPTO_SM3
+ {
+ .alg = QCRYPTO_HASH_ALGO_SM3,
+ .hex_digest =
+ "760e3799332bc913819b930085360ddb"
+ "c05529261313d5b15b75bab4fd7ae91e",
+ },
+#endif
};
static const char hex[] = "0123456789abcdef";
@@ -325,6 +325,22 @@ static QCryptoPbkdfTestData test_data[] = {
"\xce\xbf\x91\x14\x8b\x5c\x48\x41",
.nout = 32
},
+#ifdef CONFIG_CRYPTO_SM3
+ {
+ .path = "/crypto/pbkdf/nonrfc/sm3/iter2",
+ .hash = QCRYPTO_HASH_ALGO_SM3,
+ .iterations = 2,
+ .key = "password",
+ .nkey = 8,
+ .salt = "ATHENA.MIT.EDUraeburn",
+ .nsalt = 21,
+ .out = "\x48\x71\x1b\x58\xa3\xcb\xce\x06"
+ "\xba\xad\x77\xa8\xb5\xb9\xd8\x07"
+ "\x6a\xe2\xb3\x5b\x95\xce\xc8\xce"
+ "\xe7\xb1\xcb\xee\x61\xdf\x04\xea",
+ .nout = 32
+ },
+#endif
#if 0
{
.path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",