From: Hyman Huang <yong.huang@smartx.com>
To: qemu-devel <qemu-devel@nongnu.org>
Cc: "Daniel P . Berrangé" <berrange@redhat.com>,
"Eric Blake" <eblake@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Hyman Huang" <yong.huang@smartx.com>
Subject: [PATCH] crypto: Introduce SM4 symmetric cipher algorithm
Date: Mon, 27 Nov 2023 23:55:34 +0800 [thread overview]
Message-ID: <386ee33ff8f1dc4e8416b037e548ae36c983d054.1701100272.git.yong.huang@smartx.com> (raw)
Introduce the SM4 cipher algorithms (OSCCA GB/T 32907-2016).
SM4 (GBT.32907-2016) is a cryptographic standard issued by the
Organization of State Commercial Administration of China (OSCCA)
as an authorized cryptographic algorithms for the use within China.
Signed-off-by: Hyman Huang <yong.huang@smartx.com>
---
crypto/block-luks.c | 7 ++++++
crypto/cipher-gcrypt.c.inc | 4 ++++
crypto/cipher-nettle.c.inc | 42 +++++++++++++++++++++++++++++++++
crypto/cipher.c | 2 ++
qapi/crypto.json | 5 +++-
tests/unit/test-crypto-cipher.c | 11 +++++++++
6 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index fb01ec38bb..1cb7f21a05 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -95,12 +95,19 @@ qcrypto_block_luks_cipher_size_map_twofish[] = {
{ 0, 0 },
};
+static const QCryptoBlockLUKSCipherSizeMap
+qcrypto_block_luks_cipher_size_map_sm4[] = {
+ { 16, QCRYPTO_CIPHER_ALG_SM4},
+ { 0, 0 },
+};
+
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 },
+ { "sm4", qcrypto_block_luks_cipher_size_map_sm4},
};
QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSKeySlot) != 48);
diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc
index a6a0117717..03af50b0c3 100644
--- a/crypto/cipher-gcrypt.c.inc
+++ b/crypto/cipher-gcrypt.c.inc
@@ -35,6 +35,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
case QCRYPTO_CIPHER_ALG_SERPENT_256:
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
+ case QCRYPTO_CIPHER_ALG_SM4:
break;
default:
return false;
@@ -219,6 +220,9 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
gcryalg = GCRY_CIPHER_TWOFISH;
break;
+ case QCRYPTO_CIPHER_ALG_SM4:
+ gcryalg = GCRY_CIPHER_SM4;
+ break;
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 24cc61f87b..cd2ca0c7b5 100644
--- a/crypto/cipher-nettle.c.inc
+++ b/crypto/cipher-nettle.c.inc
@@ -30,6 +30,7 @@
#include <nettle/serpent.h>
#include <nettle/twofish.h>
#include <nettle/ctr.h>
+#include <nettle/sm4.h>
#ifndef CONFIG_QEMU_PRIVATE_XTS
#include <nettle/xts.h>
#endif
@@ -426,6 +427,28 @@ DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish,
QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE,
twofish_encrypt_native, twofish_decrypt_native)
+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)
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
@@ -443,6 +466,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
case QCRYPTO_CIPHER_ALG_TWOFISH_192:
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
+ case QCRYPTO_CIPHER_ALG_SM4:
break;
default:
return false;
@@ -702,6 +726,24 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
return &ctx->base;
}
+ 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;
+ }
+
default:
error_setg(errp, "Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_str(alg));
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 74b09a5b26..048ceaa6a3 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -38,6 +38,7 @@ 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,
+ [QCRYPTO_CIPHER_ALG_SM4] = 16,
};
static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
@@ -53,6 +54,7 @@ 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,
+ [QCRYPTO_CIPHER_ALG_SM4] = 16,
};
static const bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
diff --git a/qapi/crypto.json b/qapi/crypto.json
index fd3d46ebd1..95fa10bb6d 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -94,6 +94,8 @@
#
# @twofish-256: Twofish with 256 bit / 32 byte keys
#
+# @sm4: SM4 with 128 bit / 16 byte keys (since 8.2)
+#
# Since: 2.6
##
{ 'enum': 'QCryptoCipherAlgorithm',
@@ -102,7 +104,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/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c
index d9d9d078ff..80a4984e43 100644
--- a/tests/unit/test-crypto-cipher.c
+++ b/tests/unit/test-crypto-cipher.c
@@ -382,6 +382,17 @@ static QCryptoCipherTestData test_data[] = {
.plaintext = "90afe91bb288544f2c32dc239b2635e6",
.ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa",
},
+ {
+ /* SM4, GB/T 32907-2016, Appendix A.1 */
+ .path = "/crypto/cipher/sm4",
+ .alg = QCRYPTO_CIPHER_ALG_SM4,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "0123456789abcdeffedcba9876543210",
+ .plaintext =
+ "0123456789abcdeffedcba9876543210",
+ .ciphertext =
+ "681edf34d206965e86b3e94f536e4246",
+ },
{
/* #1 32 byte key, 32 byte PTX */
.path = "/crypto/cipher/aes-xts-128-1",
--
2.39.1
next reply other threads:[~2023-11-27 15:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-27 15:55 Hyman Huang [this message]
2023-11-27 16:11 ` [PATCH] crypto: Introduce SM4 symmetric cipher algorithm Daniel P. Berrangé
2023-11-27 16:38 ` Yong Huang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=386ee33ff8f1dc4e8416b037e548ae36c983d054.1701100272.git.yong.huang@smartx.com \
--to=yong.huang@smartx.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=eblake@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).