diff --git a/crypto/block-luks.c b/crypto/block-luks.c index fe8f04ffb294d80ce55957cab72f2dd14e0d496d..24789857b2bf9ba46d12831473171d9487802059 100644 --- a/crypto/block-luks.c +++ b/crypto/block-luks.c @@ -126,12 +126,23 @@ qcrypto_block_luks_cipher_size_map_twofish[] = { { 0, 0 }, }; +#ifdef CONFIG_CRYPTO_SM4 +static const QCryptoBlockLUKSCipherSizeMap +qcrypto_block_luks_cipher_size_map_sm4[] = { + { 16, QCRYPTO_CIPHER_ALG_SM4}, + { 0, 0 }, +}; +#endif + static const QCryptoBlockLUKSCipherNameMap qcrypto_block_luks_cipher_name_map[] = { { "aes", qcrypto_block_luks_cipher_size_map_aes }, { "cast5", qcrypto_block_luks_cipher_size_map_cast5 }, { "serpent", qcrypto_block_luks_cipher_size_map_serpent }, { "twofish", qcrypto_block_luks_cipher_size_map_twofish }, +#ifdef CONFIG_CRYPTO_SM4 + { "sm4", qcrypto_block_luks_cipher_size_map_sm4}, +#endif }; @@ -1340,7 +1351,7 @@ qcrypto_block_luks_create(QCryptoBlock *block, luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS; } if (!luks_opts.has_cipher_alg) { - luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256; + luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_SM4; } if (!luks_opts.has_cipher_mode) { luks_opts.cipher_mode = QCRYPTO_CIPHER_MODE_XTS; diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc index a6a0117717f5bc1061e91612981ee26eaa8a1d3b..1377cbaf147a019e4b0a6899cb14d5046c15ef2c 100644 --- a/crypto/cipher-gcrypt.c.inc +++ b/crypto/cipher-gcrypt.c.inc @@ -35,6 +35,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, case QCRYPTO_CIPHER_ALG_SERPENT_256: case QCRYPTO_CIPHER_ALG_TWOFISH_128: case QCRYPTO_CIPHER_ALG_TWOFISH_256: +#ifdef CONFIG_CRYPTO_SM4 + case QCRYPTO_CIPHER_ALG_SM4: +#endif break; default: return false; @@ -219,6 +222,11 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, case QCRYPTO_CIPHER_ALG_TWOFISH_256: gcryalg = GCRY_CIPHER_TWOFISH; break; +#ifdef CONFIG_CRYPTO_SM4 + case QCRYPTO_CIPHER_ALG_SM4: + gcryalg = GCRY_CIPHER_SM4; + break; +#endif default: error_setg(errp, "Unsupported cipher algorithm %s", QCryptoCipherAlgorithm_str(alg)); diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc index 24cc61f87bfc4ae7ab8ff523a4105a67bace67a1..b9a0cc0ac12c1cead899b82157da78f7a68588db 100644 --- a/crypto/cipher-nettle.c.inc +++ b/crypto/cipher-nettle.c.inc @@ -33,6 +33,9 @@ #ifndef CONFIG_QEMU_PRIVATE_XTS #include #endif +#ifdef CONFIG_CRYPTO_SM4 +#include +#endif static inline bool qcrypto_length_check(size_t len, size_t blocksize, Error **errp) @@ -45,6 +48,30 @@ static inline bool qcrypto_length_check(size_t len, size_t blocksize, return true; } +#ifdef CONFIG_CRYPTO_SM4 +typedef struct QCryptoNettleSm4 { + QCryptoCipher base; + struct sm4_ctx key[2]; +} QCryptoNettleSm4; + +static void sm4_encrypt_native(void *ctx, size_t length, + uint8_t *dst, const uint8_t *src) +{ + struct sm4_ctx *keys = ctx; + sm4_crypt(&keys[0], length, dst, src); +} + +static void sm4_decrypt_native(void *ctx, size_t length, + uint8_t *dst, const uint8_t *src) +{ + struct sm4_ctx *keys = ctx; + sm4_crypt(&keys[1], length, dst, src); +} + +DEFINE_ECB(qcrypto_nettle_sm4, + QCryptoNettleSm4, SM4_BLOCK_SIZE, + sm4_encrypt_native, sm4_decrypt_native) +#endif static void qcrypto_cipher_ctx_free(QCryptoCipher *ctx) { @@ -443,6 +470,9 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, case QCRYPTO_CIPHER_ALG_TWOFISH_128: case QCRYPTO_CIPHER_ALG_TWOFISH_192: case QCRYPTO_CIPHER_ALG_TWOFISH_256: +#ifdef CONFIG_CRYPTO_SM4 + case QCRYPTO_CIPHER_ALG_SM4: +#endif break; default: return false; @@ -701,6 +731,25 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, return &ctx->base; } +#ifdef CONFIG_CRYPTO_SM4 + case QCRYPTO_CIPHER_ALG_SM4: + { + QCryptoNettleSm4 *ctx = g_new0(QCryptoNettleSm4, 1); + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + ctx->base.driver = &qcrypto_nettle_sm4_driver_ecb; + break; + default: + goto bad_cipher_mode; + } + + sm4_set_encrypt_key(&ctx->key[0], key); + sm4_set_decrypt_key(&ctx->key[1], key); + + return &ctx->base; + } +#endif default: error_setg(errp, "Unsupported cipher algorithm %s", diff --git a/crypto/cipher.c b/crypto/cipher.c index 74b09a5b261bae00c01afa788dbca99017f4110e..425e9cca83739f32d75974b8312c28f69a006dbf 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -38,6 +38,9 @@ static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = { [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16, [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 24, [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 32, +#ifdef CONFIG_CRYPTO_SM4 + [QCRYPTO_CIPHER_ALG_SM4] = 16, +#endif }; static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { @@ -53,6 +56,9 @@ static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = { [QCRYPTO_CIPHER_ALG_TWOFISH_128] = 16, [QCRYPTO_CIPHER_ALG_TWOFISH_192] = 16, [QCRYPTO_CIPHER_ALG_TWOFISH_256] = 16, +#ifdef CONFIG_CRYPTO_SM4 + [QCRYPTO_CIPHER_ALG_SM4] = 16, +#endif }; static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = { diff --git a/crypto/hash-gcrypt.c b/crypto/hash-gcrypt.c index 829e48258d326c3d8a9c7a5d2ef85a06a0dabfb2..d3bdfe5633edeea4defb30ac16a6f40674b95584 100644 --- a/crypto/hash-gcrypt.c +++ b/crypto/hash-gcrypt.c @@ -33,6 +33,9 @@ static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = { [QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384, [QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512, [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160, +#ifdef CONFIG_CRYPTO_SM3 + [QCRYPTO_HASH_ALG_SM3] = GCRY_MD_SM3, +#endif }; gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg) diff --git a/crypto/hash.c b/crypto/hash.c index b0f8228bdcb4a0b39e194065570065881ac51396..3613a5bcaadf588dbeae53a67a362ff8eafbaa68 100644 --- a/crypto/hash.c +++ b/crypto/hash.c @@ -30,6 +30,9 @@ static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = { [QCRYPTO_HASH_ALG_SHA384] = 48, [QCRYPTO_HASH_ALG_SHA512] = 64, [QCRYPTO_HASH_ALG_RIPEMD160] = 20, +#ifdef CONFIG_CRYPTO_SM4 + [QCRYPTO_HASH_ALG_SM3] = 32, +#endif }; size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg) diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c index 0c6f9797114c26f56301da6d9a97de98014046bd..888afb86ed2b2ab70586b4752f1df5f98aa1ebd6 100644 --- a/crypto/hmac-gcrypt.c +++ b/crypto/hmac-gcrypt.c @@ -26,6 +26,9 @@ static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = { [QCRYPTO_HASH_ALG_SHA384] = GCRY_MAC_HMAC_SHA384, [QCRYPTO_HASH_ALG_SHA512] = GCRY_MAC_HMAC_SHA512, [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MAC_HMAC_RMD160, +#ifdef CONFIG_CRYPTO_SM3 + [QCRYPTO_HASH_ALG_SM3] = GCRY_MAC_HMAC_SM3, +#endif }; typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt; diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c index a8d8e64f4d46bbb65f8d0ef71cbe20c08bca31ed..f90df262bb00af72cf90c2b509e561cc0db1b587 100644 --- a/crypto/pbkdf-gcrypt.c +++ b/crypto/pbkdf-gcrypt.c @@ -33,7 +33,10 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) case QCRYPTO_HASH_ALG_SHA384: case QCRYPTO_HASH_ALG_SHA512: case QCRYPTO_HASH_ALG_RIPEMD160: +#ifdef CONFIG_CRYPTO_SM3 + case QCRYPTO_HASH_ALG_SM3: return true; +#endif default: return false; } @@ -54,6 +57,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, [QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384, [QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512, [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160, +#ifdef CONFIG_CRYPTO_SM3 + [QCRYPTO_HASH_ALG_SM3] = GCRY_MD_SM3, +#endif }; int ret; diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c index 118c68da831d998fe2469e86fbd39ebff06781da..cee658c158b253b5c539e828b391ed66536315ef 100644 --- a/ebpf/ebpf_rss.c +++ b/ebpf/ebpf_rss.c @@ -49,7 +49,7 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx) goto error; } - bpf_program__set_socket_filter(rss_bpf_ctx->progs.tun_rss_steering_prog); + bpf_program__set_type(rss_bpf_ctx->progs.tun_rss_steering_prog, BPF_PROG_TYPE_SOCKET_FILTER); if (rss_bpf__load(rss_bpf_ctx)) { trace_ebpf_error("eBPF RSS", "can not load RSS program"); diff --git a/meson.build b/meson.build index 45bc69bf0c718199c6af166c777b96472ac6c009..7675bdcb811348ed3b0a5d9e6690ade0ce458c95 100644 --- a/meson.build +++ b/meson.build @@ -1010,6 +1010,8 @@ endif # gcrypt over nettle for performance reasons. gcrypt = not_found nettle = not_found +crypto_sm4 = not_found +crypto_sm3 = not_found xts = 'none' if get_option('nettle').enabled() and get_option('gcrypt').enabled() @@ -1035,6 +1037,28 @@ if not gnutls_crypto.found() gcrypt, cc.find_library('gpg-error', required: true, kwargs: static_kwargs)]) endif + crypto_sm4 = gcrypt + # SM4 ALG is available in libgcrypt >= 1.9 + if gcrypt.found() and not cc.links(''' + #include + int main(void) { + gcry_cipher_hd_t handler; + gcry_cipher_open(&handler, GCRY_CIPHER_SM4, GCRY_CIPHER_MODE_ECB, 0); + return 0; + }''', dependencies: gcrypt) + crypto_sm4 = not_found + endif + crypto_sm3 = gcrypt + # SM3 ALG is available in libgcrypt >= 1.8 + if gcrypt.found() and not cc.links(''' + #include + 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', @@ -1044,6 +1068,32 @@ if not gnutls_crypto.found() if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle) xts = 'private' endif + crypto_sm4 = nettle + # SM4 ALG is available in nettle >= 3.9 + if nettle.found() and not cc.links(''' + #include + int main(void) { + struct sm4_ctx ctx; + unsigned char key[16] = {0}; + sm4_set_encrypt_key(&ctx, key); + return 0; + }''', dependencies: nettle) + crypto_sm4 = not_found + endif + crypto_sm3 = nettle + # SM3 ALG is available in nettle >= 3.4 + if nettle.found() and not cc.links(''' + #include + int main(void) { + struct sm3_ctx ctx; + unsigned char data[64] = {0}; + sm3_init(&ctx); + sm3_update(&ctx, 64, data); + sm3_digest(&ctx, 32, data); + return 0; + }''', dependencies: nettle) + crypto_sm3 = not_found + endif endif endif @@ -1487,6 +1537,8 @@ config_host_data.set('CONFIG_GNUTLS', gnutls.found()) config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.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_QEMU_PRIVATE_XTS', xts == 'private') config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim) config_host_data.set('CONFIG_STATX', has_statx) @@ -3432,6 +3484,8 @@ summary_info += {'nettle': nettle} 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 += {'crypto afalg': config_host.has_key('CONFIG_AF_ALG')} summary_info += {'rng-none': config_host.has_key('CONFIG_RNG_NONE')} summary_info += {'Linux keyring': config_host.has_key('CONFIG_SECRET_KEYRING')} diff --git a/qapi/crypto.json b/qapi/crypto.json index 1ec54c15ca5f148c62d08d5c650af205415bf4ec..e90ab3c22efa56042162b0a860c1b6da9f8bb029 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -55,7 +55,7 @@ ## { 'enum': 'QCryptoHashAlgorithm', 'prefix': 'QCRYPTO_HASH_ALG', - 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']} + 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160', 'sm3']} ## @@ -83,8 +83,8 @@ 'des', '3des', 'cast5-128', 'serpent-128', 'serpent-192', 'serpent-256', - 'twofish-128', 'twofish-192', 'twofish-256']} - + 'twofish-128', 'twofish-192', 'twofish-256', + 'sm4']} ## # @QCryptoCipherMode: diff --git a/tests/test_encvm/create_domain_xml.sh b/tests/test_encvm/create_domain_xml.sh new file mode 100644 index 0000000000000000000000000000000000000000..3275b64dcb82f09fd32d109c8b37dfdac11fe114 --- /dev/null +++ b/tests/test_encvm/create_domain_xml.sh @@ -0,0 +1,22 @@ +#!/bin/bash + + +# 检查是否提供了足够的参数 +if [ "$#" -ne 2 ]; then + echo "Usage: $0 UUID VOLUME_PATH" + exit 1 +fi + +# 读取参数 +UUID=$1 +VOLUME=$2 + +# 指定模板文件和输出文件 +TEMPLATE_FILE="vm_kvm.xml" +OUTPUT_FILE="domain_${UUID}.xml" + +# 读取模板文件并替换占位符,然后写入到新的文件 +sed "s|\${uuid}|${UUID}|g; s|\${volume}|${VOLUME}|g" $TEMPLATE_FILE > $OUTPUT_FILE + +echo "Output written to $OUTPUT_FILE" + diff --git a/tests/test_encvm/create_secret_xml.sh b/tests/test_encvm/create_secret_xml.sh new file mode 100644 index 0000000000000000000000000000000000000000..ad2d8bd8e7a54991afe8b61f4ebc6b3adde28db9 --- /dev/null +++ b/tests/test_encvm/create_secret_xml.sh @@ -0,0 +1,22 @@ +#!/bin/bash + + +# 检查是否提供了足够的参数 +if [ "$#" -ne 2 ]; then + echo "Usage: $0 UUID VOLUME_PATH" + exit 1 +fi + +# 读取参数 +UUID=$1 +VOLUME=$2 + +# 指定模板文件和输出文件 +TEMPLATE_FILE="secret.xml" +OUTPUT_FILE="secxml_${UUID}.xml" + +# 读取模板文件并替换占位符,然后写入到新的文件 +sed "s|\${uuid}|${UUID}|g; s|\${volume}|${VOLUME}|g" $TEMPLATE_FILE > $OUTPUT_FILE + +echo "Output written to $OUTPUT_FILE" + diff --git a/tests/test_encvm/createsecvm.sh b/tests/test_encvm/createsecvm.sh new file mode 100644 index 0000000000000000000000000000000000000000..c5bb16b16c0af47718ac4758ddefef9ed5b46db5 --- /dev/null +++ b/tests/test_encvm/createsecvm.sh @@ -0,0 +1,33 @@ +# 检查是否提供了足够的参数 +if [ "$#" -ne 2 ]; then + echo "Usage: $0 UUID VOLUME_PATH" + exit 1 +fi + +# 读取参数 +uuid=$1 +volume=$2 +echo ${uuid} + +if [ ! -f ${volume} ];then + echo "not exist ${volume}!\n" + exit 1 +fi + +sec_volume="${volume%.qcow2}_enc.qcow2" +sh -x ./create_secret_xml.sh ${uuid} ${sec_volume} +secuuid=$(virsh secret-list |grep ${sec_volume}|cut -d " " -f2) + +if [ ! -z ${secuuid} ];then + virsh secret-undefine ${secuuid} +fi +virsh secret-define secxml_${uuid}.xml +sh -x secret_set.sh ${uuid} +qemu-img convert -O qcow2 --object secret,id=sec0,data=${uuid} -o encrypt.format=luks,encrypt.key-secret=sec0,encrypt.cipher-alg=sm4,encrypt.cipher-mode=xts,encrypt.ivgen-alg=plain64,encrypt.hash-alg=sm3 ${volume} ${sec_volume} +if [ $? != 0 ];then + echo "qemu-img convert sec img error!\n" + exit 1 +fi +sh -x ./create_domain_xml.sh ${uuid} ${sec_volume} +virsh define domain_${uuid}.xml +virsh start ${uuid} diff --git a/tests/test_encvm/secret.xml b/tests/test_encvm/secret.xml new file mode 100644 index 0000000000000000000000000000000000000000..e205e53c410136ffab3201948db4eca5d41f5403 --- /dev/null +++ b/tests/test_encvm/secret.xml @@ -0,0 +1,6 @@ + + ${uuid} + + ${volume} + + diff --git a/tests/test_encvm/secret_set.sh b/tests/test_encvm/secret_set.sh new file mode 100644 index 0000000000000000000000000000000000000000..ff5940fd3acf3d05946dd579b601fefb23024fb0 --- /dev/null +++ b/tests/test_encvm/secret_set.sh @@ -0,0 +1,11 @@ +#!/bin/sh +if [ "$#" -ne 1 ]; then + echo "Usage: $0 UUID" + exit 1 +fi + +# 读取参数 +uuid=$1 +seuuid=`echo -n ${uuid} |base64` +echo ${seuuid} >/tmp/${uuid} +virsh secret-set-value ${uuid} --file /tmp/${uuid} diff --git a/tests/test_encvm/template.xml b/tests/test_encvm/template.xml new file mode 100644 index 0000000000000000000000000000000000000000..c63983c319dd03bef9e74bbe9448260d84e42f12 --- /dev/null +++ b/tests/test_encvm/template.xml @@ -0,0 +1,119 @@ + + + ${uuid} + ${uuid} + 524288 + 16777216 + 16 + + /machine + + + hvm + + + + + + + + qemu64 + + + + + + + destroy + restart + destroy + + + + + + /usr/bin/qemu-system-x86_64 + + + + + + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +