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>
[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)
#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,
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 {
.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)
[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)
[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 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;
};
.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)
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;
[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;
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;
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) {
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,
#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 */
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()
}''', 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',
}''', 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
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)
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}
# @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:
"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="
"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,
[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,
[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,
[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";
"94964ed4c1155b62b668c241d67279e5"
"8a711676",
},
+#ifdef CONFIG_CRYPTO_SM3
+ {
+ .alg = QCRYPTO_HASH_ALGO_SM3,
+ .hex_digest =
+ "760e3799332bc913819b930085360ddb"
+ "c05529261313d5b15b75bab4fd7ae91e",
+ },
+#endif
};
static const char hex[] = "0123456789abcdef";
"\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",