Selaa lähdekoodia

Merge tag 'crypto-fixes-pull-request' of https://gitlab.com/berrange/qemu into staging

* Remove deprecated 'loaded' property from crypto objects
* Fix error checking of hash function in gcrypt
* Perform runtime check for hash functions in gcrypt
* Add SM3 hash function to pbkdf

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmcqZpkACgkQvobrtBUQ
# T992Gg//TMfrdS8CtjzCMSDbPuGu4NSkNa0nm3vnz6KOyOoZ7MYDjhWFXux0xckG
# cetuWBPQR/prQorzVje2ojEa3aUWQ4AxOn6xbHg1bXl+nCLB2iu9RcKy0vc/pZ2i
# mFI3HIFyZjETJ/9NXgy7fZFTNmiMAucYwtxfHXwcvRXHH8cBGIwiXpAWpAOo2pXd
# iS90PDxxd20anykuHBmN9RSXcLTaEqT5pIMCowqPVh0vwdnLVi+5UpYrwR6JYIG7
# GxsnoXXl5aB786gEL0M2p4XTfJs0zESVMAt2sjxD8gtVDERd87x1cCHLkuVnb3GS
# HtHdxRT4TeUjwvYStU9lNpHT3wC1vGaU8x7SBKZ9VensbR+OERWlkdJGRixXc9FT
# 1RyRfJzUbCk7wjJFfNmhMvEaE8sSvhxIc1JVQVCDBxqpMYTFOmLZqhD0vpcxkyot
# go1+y0+6wlxjw2/JlOG0CDDDnYwOpRCETYTHm0G0/Gm4izu/YQOGqCC/0YA+mOhX
# Gkg230gj2BzWYFvU7iGotEY3yWN6qRN06+GRlImDSNmFr6FdEzc8u5ZvDtVuq3++
# SwvbKQ7N0sJbzmWCyB9/rNiJMu5723VW9phCmRwcUBp79fVYJpH+QOHmZixoqBf7
# oKUYxhRhzCiQQaxWG7E8Um7sDjk0LTYf29W0tebCSZuRqSnVHGM=
# =tzW1
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 05 Nov 2024 18:40:25 GMT
# gpg:                using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [full]
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>" [full]
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* tag 'crypto-fixes-pull-request' of https://gitlab.com/berrange/qemu:
  crypto: perform runtime check for hash/hmac support in gcrypt
  crypto: fix error check on gcry_md_open
  crypto: Introduce SM3 hash hmac pbkdf algorithm
  crypto: purge 'loaded' property that was not fully removed

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Peter Maydell 9 kuukautta sitten
vanhempi
commit
731d58b545

+ 6 - 3
crypto/hash-gcrypt.c

@@ -34,13 +34,16 @@ static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = {
     [QCRYPTO_HASH_ALGO_SHA384] = GCRY_MD_SHA384,
     [QCRYPTO_HASH_ALGO_SHA384] = GCRY_MD_SHA384,
     [QCRYPTO_HASH_ALGO_SHA512] = GCRY_MD_SHA512,
     [QCRYPTO_HASH_ALGO_SHA512] = GCRY_MD_SHA512,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MD_RMD160,
     [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)
 gboolean qcrypto_hash_supports(QCryptoHashAlgo alg)
 {
 {
     if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
     if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
         qcrypto_hash_alg_map[alg] != GCRY_MD_NONE) {
         qcrypto_hash_alg_map[alg] != GCRY_MD_NONE) {
-        return true;
+        return gcry_md_test_algo(qcrypto_hash_alg_map[alg]) == 0;
     }
     }
     return false;
     return false;
 }
 }
@@ -49,7 +52,7 @@ static
 QCryptoHash *qcrypto_gcrypt_hash_new(QCryptoHashAlgo alg, Error **errp)
 QCryptoHash *qcrypto_gcrypt_hash_new(QCryptoHashAlgo alg, Error **errp)
 {
 {
     QCryptoHash *hash;
     QCryptoHash *hash;
-    int ret;
+    gcry_error_t ret;
 
 
     hash = g_new(QCryptoHash, 1);
     hash = g_new(QCryptoHash, 1);
     hash->alg = alg;
     hash->alg = alg;
@@ -57,7 +60,7 @@ QCryptoHash *qcrypto_gcrypt_hash_new(QCryptoHashAlgo alg, Error **errp)
 
 
     ret = gcry_md_open((gcry_md_hd_t *) hash->opaque,
     ret = gcry_md_open((gcry_md_hd_t *) hash->opaque,
                        qcrypto_hash_alg_map[alg], 0);
                        qcrypto_hash_alg_map[alg], 0);
-    if (ret < 0) {
+    if (ret != 0) {
         error_setg(errp,
         error_setg(errp,
                    "Unable to initialize hash algorithm: %s",
                    "Unable to initialize hash algorithm: %s",
                    gcry_strerror(ret));
                    gcry_strerror(ret));

+ 14 - 0
crypto/hash-nettle.c

@@ -26,6 +26,9 @@
 #include <nettle/md5.h>
 #include <nettle/md5.h>
 #include <nettle/sha.h>
 #include <nettle/sha.h>
 #include <nettle/ripemd160.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_init)(void *ctx);
 typedef void (*qcrypto_nettle_write)(void *ctx,
 typedef void (*qcrypto_nettle_write)(void *ctx,
@@ -43,6 +46,9 @@ union qcrypto_hash_ctx {
     struct sha384_ctx sha384;
     struct sha384_ctx sha384;
     struct sha512_ctx sha512;
     struct sha512_ctx sha512;
     struct ripemd160_ctx ripemd160;
     struct ripemd160_ctx ripemd160;
+#ifdef CONFIG_CRYPTO_SM3
+    struct sm3_ctx sm3;
+#endif
 };
 };
 
 
 struct qcrypto_hash_alg {
 struct qcrypto_hash_alg {
@@ -93,6 +99,14 @@ struct qcrypto_hash_alg {
         .result = (qcrypto_nettle_result)ripemd160_digest,
         .result = (qcrypto_nettle_result)ripemd160_digest,
         .len = RIPEMD160_DIGEST_SIZE,
         .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)
 gboolean qcrypto_hash_supports(QCryptoHashAlgo alg)

+ 3 - 0
crypto/hash.c

@@ -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_SHA384]    = QCRYPTO_HASH_DIGEST_LEN_SHA384,
     [QCRYPTO_HASH_ALGO_SHA512]    = QCRYPTO_HASH_DIGEST_LEN_SHA512,
     [QCRYPTO_HASH_ALGO_SHA512]    = QCRYPTO_HASH_DIGEST_LEN_SHA512,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = QCRYPTO_HASH_DIGEST_LEN_RIPEMD160,
     [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)
 size_t qcrypto_hash_digest_len(QCryptoHashAlgo alg)

+ 4 - 1
crypto/hmac-gcrypt.c

@@ -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_SHA384] = GCRY_MAC_HMAC_SHA384,
     [QCRYPTO_HASH_ALGO_SHA512] = GCRY_MAC_HMAC_SHA512,
     [QCRYPTO_HASH_ALGO_SHA512] = GCRY_MAC_HMAC_SHA512,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MAC_HMAC_RMD160,
     [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;
 typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
@@ -37,7 +40,7 @@ bool qcrypto_hmac_supports(QCryptoHashAlgo alg)
 {
 {
     if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
     if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
         qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
         qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
-        return true;
+        return gcry_mac_test_algo(qcrypto_hmac_alg_map[alg]) == 0;
     }
     }
 
 
     return false;
     return false;

+ 11 - 0
crypto/hmac-nettle.c

@@ -38,6 +38,9 @@ struct QCryptoHmacNettle {
         struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */
         struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */
         struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */
         struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */
         struct hmac_ripemd160_ctx ripemd160_ctx;
         struct hmac_ripemd160_ctx ripemd160_ctx;
+#ifdef CONFIG_CRYPTO_SM3
+ struct hmac_sm3_ctx ctx;
+#endif
     } u;
     } u;
 };
 };
 
 
@@ -89,6 +92,14 @@ struct qcrypto_nettle_hmac_alg {
         .digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest,
         .digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest,
         .len = RIPEMD160_DIGEST_SIZE,
         .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)
 bool qcrypto_hmac_supports(QCryptoHashAlgo alg)

+ 6 - 0
crypto/pbkdf-gcrypt.c

@@ -33,6 +33,9 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgo hash)
     case QCRYPTO_HASH_ALGO_SHA384:
     case QCRYPTO_HASH_ALGO_SHA384:
     case QCRYPTO_HASH_ALGO_SHA512:
     case QCRYPTO_HASH_ALGO_SHA512:
     case QCRYPTO_HASH_ALGO_RIPEMD160:
     case QCRYPTO_HASH_ALGO_RIPEMD160:
+#ifdef CONFIG_CRYPTO_SM3
+    case QCRYPTO_HASH_ALGO_SM3:
+#endif
         return qcrypto_hash_supports(hash);
         return qcrypto_hash_supports(hash);
     default:
     default:
         return false;
         return false;
@@ -54,6 +57,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgo hash,
         [QCRYPTO_HASH_ALGO_SHA384] = GCRY_MD_SHA384,
         [QCRYPTO_HASH_ALGO_SHA384] = GCRY_MD_SHA384,
         [QCRYPTO_HASH_ALGO_SHA512] = GCRY_MD_SHA512,
         [QCRYPTO_HASH_ALGO_SHA512] = GCRY_MD_SHA512,
         [QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MD_RMD160,
         [QCRYPTO_HASH_ALGO_RIPEMD160] = GCRY_MD_RMD160,
+#ifdef CONFIG_CRYPTO_SM3
+        [QCRYPTO_HASH_ALGO_SM3] = GCRY_MD_SM3,
+#endif
     };
     };
     int ret;
     int ret;
 
 

+ 13 - 0
crypto/pbkdf-nettle.c

@@ -34,6 +34,9 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgo hash)
     case QCRYPTO_HASH_ALGO_SHA384:
     case QCRYPTO_HASH_ALGO_SHA384:
     case QCRYPTO_HASH_ALGO_SHA512:
     case QCRYPTO_HASH_ALGO_SHA512:
     case QCRYPTO_HASH_ALGO_RIPEMD160:
     case QCRYPTO_HASH_ALGO_RIPEMD160:
+#ifdef CONFIG_CRYPTO_SM3
+    case QCRYPTO_HASH_ALGO_SM3:
+#endif
         return true;
         return true;
     default:
     default:
         return false;
         return false;
@@ -55,6 +58,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgo hash,
         struct hmac_sha384_ctx sha384;
         struct hmac_sha384_ctx sha384;
         struct hmac_sha512_ctx sha512;
         struct hmac_sha512_ctx sha512;
         struct hmac_ripemd160_ctx ripemd160;
         struct hmac_ripemd160_ctx ripemd160;
+#ifdef CONFIG_CRYPTO_SM3
+        struct hmac_sm3_ctx sm3;
+#endif
     } ctx;
     } ctx;
 
 
     if (iterations > UINT_MAX) {
     if (iterations > UINT_MAX) {
@@ -106,6 +112,13 @@ int qcrypto_pbkdf2(QCryptoHashAlgo hash,
         PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest,
         PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest,
                RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
                RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
         break;
         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:
     default:
         error_setg_errno(errp, ENOSYS,
         error_setg_errno(errp, ENOSYS,

+ 0 - 12
crypto/secret_common.c

@@ -191,15 +191,6 @@ qcrypto_secret_complete(UserCreatable *uc, Error **errp)
 }
 }
 
 
 
 
-static bool
-qcrypto_secret_prop_get_loaded(Object *obj,
-                               Error **errp G_GNUC_UNUSED)
-{
-    QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
-    return secret->rawdata != NULL;
-}
-
-
 static void
 static void
 qcrypto_secret_prop_set_format(Object *obj,
 qcrypto_secret_prop_set_format(Object *obj,
                                int value,
                                int value,
@@ -278,9 +269,6 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data)
 
 
     ucc->complete = qcrypto_secret_complete;
     ucc->complete = qcrypto_secret_complete;
 
 
-    object_class_property_add_bool(oc, "loaded",
-                                   qcrypto_secret_prop_get_loaded,
-                                   NULL);
     object_class_property_add_enum(oc, "format",
     object_class_property_add_enum(oc, "format",
                                    "QCryptoSecretFormat",
                                    "QCryptoSecretFormat",
                                    &QCryptoSecretFormat_lookup,
                                    &QCryptoSecretFormat_lookup,

+ 0 - 35
crypto/tlscredsanon.c

@@ -127,37 +127,6 @@ qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp)
 }
 }
 
 
 
 
-#ifdef CONFIG_GNUTLS
-
-
-static bool
-qcrypto_tls_creds_anon_prop_get_loaded(Object *obj,
-                                       Error **errp G_GNUC_UNUSED)
-{
-    QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj);
-
-    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
-        return creds->data.server != NULL;
-    } else {
-        return creds->data.client != NULL;
-    }
-}
-
-
-#else /* ! CONFIG_GNUTLS */
-
-
-static bool
-qcrypto_tls_creds_anon_prop_get_loaded(Object *obj G_GNUC_UNUSED,
-                                       Error **errp G_GNUC_UNUSED)
-{
-    return false;
-}
-
-
-#endif /* ! CONFIG_GNUTLS */
-
-
 static void
 static void
 qcrypto_tls_creds_anon_finalize(Object *obj)
 qcrypto_tls_creds_anon_finalize(Object *obj)
 {
 {
@@ -173,10 +142,6 @@ qcrypto_tls_creds_anon_class_init(ObjectClass *oc, void *data)
     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 
 
     ucc->complete = qcrypto_tls_creds_anon_complete;
     ucc->complete = qcrypto_tls_creds_anon_complete;
-
-    object_class_property_add_bool(oc, "loaded",
-                                   qcrypto_tls_creds_anon_prop_get_loaded,
-                                   NULL);
 }
 }
 
 
 
 

+ 0 - 34
crypto/tlscredspsk.c

@@ -206,37 +206,6 @@ qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp)
 }
 }
 
 
 
 
-#ifdef CONFIG_GNUTLS
-
-
-static bool
-qcrypto_tls_creds_psk_prop_get_loaded(Object *obj,
-                                      Error **errp G_GNUC_UNUSED)
-{
-    QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);
-
-    if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
-        return creds->data.server != NULL;
-    } else {
-        return creds->data.client != NULL;
-    }
-}
-
-
-#else /* ! CONFIG_GNUTLS */
-
-
-static bool
-qcrypto_tls_creds_psk_prop_get_loaded(Object *obj G_GNUC_UNUSED,
-                                      Error **errp G_GNUC_UNUSED)
-{
-    return false;
-}
-
-
-#endif /* ! CONFIG_GNUTLS */
-
-
 static void
 static void
 qcrypto_tls_creds_psk_finalize(Object *obj)
 qcrypto_tls_creds_psk_finalize(Object *obj)
 {
 {
@@ -273,9 +242,6 @@ qcrypto_tls_creds_psk_class_init(ObjectClass *oc, void *data)
 
 
     ucc->complete = qcrypto_tls_creds_psk_complete;
     ucc->complete = qcrypto_tls_creds_psk_complete;
 
 
-    object_class_property_add_bool(oc, "loaded",
-                                   qcrypto_tls_creds_psk_prop_get_loaded,
-                                   NULL);
     object_class_property_add_str(oc, "username",
     object_class_property_add_str(oc, "username",
                                   qcrypto_tls_creds_psk_prop_get_username,
                                   qcrypto_tls_creds_psk_prop_get_username,
                                   qcrypto_tls_creds_psk_prop_set_username);
                                   qcrypto_tls_creds_psk_prop_set_username);

+ 0 - 30
crypto/tlscredsx509.c

@@ -695,33 +695,6 @@ qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp)
 }
 }
 
 
 
 
-#ifdef CONFIG_GNUTLS
-
-
-static bool
-qcrypto_tls_creds_x509_prop_get_loaded(Object *obj,
-                                       Error **errp G_GNUC_UNUSED)
-{
-    QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
-
-    return creds->data != NULL;
-}
-
-
-#else /* ! CONFIG_GNUTLS */
-
-
-static bool
-qcrypto_tls_creds_x509_prop_get_loaded(Object *obj G_GNUC_UNUSED,
-                                       Error **errp G_GNUC_UNUSED)
-{
-    return false;
-}
-
-
-#endif /* ! CONFIG_GNUTLS */
-
-
 static void
 static void
 qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
 qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
                                        bool value,
                                        bool value,
@@ -838,9 +811,6 @@ qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data)
 
 
     ucc->complete = qcrypto_tls_creds_x509_complete;
     ucc->complete = qcrypto_tls_creds_x509_complete;
 
 
-    object_class_property_add_bool(oc, "loaded",
-                                   qcrypto_tls_creds_x509_prop_get_loaded,
-                                   NULL);
     object_class_property_add_bool(oc, "sanity-check",
     object_class_property_add_bool(oc, "sanity-check",
                                    qcrypto_tls_creds_x509_prop_get_sanity,
                                    qcrypto_tls_creds_x509_prop_get_sanity,
                                    qcrypto_tls_creds_x509_prop_set_sanity);
                                    qcrypto_tls_creds_x509_prop_set_sanity);

+ 3 - 3
docs/about/removed-features.rst

@@ -355,13 +355,13 @@ The ``-writeconfig`` option was not able to serialize the entire contents
 of the QEMU command line.  It is thus considered a failed experiment
 of the QEMU command line.  It is thus considered a failed experiment
 and removed without a replacement.
 and removed without a replacement.
 
 
-``loaded`` property of ``secret`` and ``secret_keyring`` objects (removed in 7.1)
-'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+``loaded`` property of secret and TLS credential objects (removed in 9.2)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 
 
 The ``loaded=on`` option in the command line or QMP ``object-add`` either had
 The ``loaded=on`` option in the command line or QMP ``object-add`` either had
 no effect (if ``loaded`` was the last option) or caused options to be
 no effect (if ``loaded`` was the last option) or caused options to be
 effectively ignored as if they were not given.  The property is therefore
 effectively ignored as if they were not given.  The property is therefore
-useless and should simply be removed.
+useless and has been removed.
 
 
 ``opened`` property of ``rng-*`` objects (removed in 7.1)
 ``opened`` property of ``rng-*`` objects (removed in 7.1)
 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''

+ 1 - 0
include/crypto/hash.h

@@ -31,6 +31,7 @@
 #define QCRYPTO_HASH_DIGEST_LEN_SHA384    48
 #define QCRYPTO_HASH_DIGEST_LEN_SHA384    48
 #define QCRYPTO_HASH_DIGEST_LEN_SHA512    64
 #define QCRYPTO_HASH_DIGEST_LEN_SHA512    64
 #define QCRYPTO_HASH_DIGEST_LEN_RIPEMD160 20
 #define QCRYPTO_HASH_DIGEST_LEN_RIPEMD160 20
+#define QCRYPTO_HASH_DIGEST_LEN_SM3       32
 
 
 /* See also "QCryptoHashAlgo" defined in qapi/crypto.json */
 /* See also "QCryptoHashAlgo" defined in qapi/crypto.json */
 
 

+ 39 - 0
meson.build

@@ -1760,6 +1760,7 @@ gcrypt = not_found
 nettle = not_found
 nettle = not_found
 hogweed = not_found
 hogweed = not_found
 crypto_sm4 = not_found
 crypto_sm4 = not_found
+crypto_sm3 = not_found
 xts = 'none'
 xts = 'none'
 
 
 if get_option('nettle').enabled() and get_option('gcrypt').enabled()
 if get_option('nettle').enabled() and get_option('gcrypt').enabled()
@@ -1795,6 +1796,17 @@ if not gnutls_crypto.found()
       }''', dependencies: gcrypt)
       }''', dependencies: gcrypt)
       crypto_sm4 = not_found
       crypto_sm4 = not_found
     endif
     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
   endif
   if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
   if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
     nettle = dependency('nettle', version: '>=3.4',
     nettle = dependency('nettle', version: '>=3.4',
@@ -1815,6 +1827,31 @@ if not gnutls_crypto.found()
       }''', dependencies: nettle)
       }''', dependencies: nettle)
       crypto_sm4 = not_found
       crypto_sm4 = not_found
     endif
     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
 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_GCRYPT', gcrypt.found())
 config_host_data.set('CONFIG_NETTLE', nettle.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_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_HOGWEED', hogweed.found())
 config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
 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_MALLOC_TRIM', has_malloc_trim)
@@ -4596,6 +4634,7 @@ if nettle.found()
    summary_info += {'  XTS':             xts != 'private'}
    summary_info += {'  XTS':             xts != 'private'}
 endif
 endif
 summary_info += {'SM4 ALG support':   crypto_sm4}
 summary_info += {'SM4 ALG support':   crypto_sm4}
+summary_info += {'SM3 ALG support':   crypto_sm3}
 summary_info += {'AF_ALG support':    have_afalg}
 summary_info += {'AF_ALG support':    have_afalg}
 summary_info += {'rng-none':          get_option('rng_none')}
 summary_info += {'rng-none':          get_option('rng_none')}
 summary_info += {'Linux keyring':     have_keyring}
 summary_info += {'Linux keyring':     have_keyring}

+ 6 - 48
qapi/crypto.json

@@ -55,11 +55,12 @@
 # @sha512: SHA-512.  (since 2.7)
 # @sha512: SHA-512.  (since 2.7)
 #
 #
 # @ripemd160: RIPEMD-160.  (since 2.7)
 # @ripemd160: RIPEMD-160.  (since 2.7)
+# @sm3: SM3. (since 9.2.0)
 #
 #
 # Since: 2.6
 # Since: 2.6
 ##
 ##
 { 'enum': 'QCryptoHashAlgo',
 { 'enum': 'QCryptoHashAlgo',
-  'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']}
+  'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160', 'sm3']}
 
 
 ##
 ##
 # @QCryptoCipherAlgo:
 # @QCryptoCipherAlgo:
@@ -419,11 +420,6 @@
 #
 #
 # Properties for objects of classes derived from secret-common.
 # Properties for objects of classes derived from secret-common.
 #
 #
-# @loaded: if true, the secret is loaded immediately when applying
-#     this option and will probably fail when processing the next
-#     option.  Don't use; only provided for compatibility.
-#     (default: false)
-#
 # @format: the data format that the secret is provided in
 # @format: the data format that the secret is provided in
 #     (default: raw)
 #     (default: raw)
 #
 #
@@ -436,16 +432,10 @@
 #     16-byte IV.  Mandatory if @keyid is given.  Ignored if @keyid is
 #     16-byte IV.  Mandatory if @keyid is given.  Ignored if @keyid is
 #     absent.
 #     absent.
 #
 #
-# Features:
-#
-# @deprecated: Member @loaded is deprecated.  Setting true doesn't
-#     make sense, and false is already the default.
-#
 # Since: 2.6
 # Since: 2.6
 ##
 ##
 { 'struct': 'SecretCommonProperties',
 { 'struct': 'SecretCommonProperties',
-  'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] },
-            '*format': 'QCryptoSecretFormat',
+  'data': { '*format': 'QCryptoSecretFormat',
             '*keyid': 'str',
             '*keyid': 'str',
             '*iv': 'str' } }
             '*iv': 'str' } }
 
 
@@ -512,58 +502,32 @@
 #
 #
 # Properties for tls-creds-anon objects.
 # Properties for tls-creds-anon objects.
 #
 #
-# @loaded: if true, the credentials are loaded immediately when
-#     applying this option and will ignore options that are processed
-#     later.  Don't use; only provided for compatibility.
-#     (default: false)
-#
-# Features:
-#
-# @deprecated: Member @loaded is deprecated.  Setting true doesn't
-#     make sense, and false is already the default.
-#
 # Since: 2.5
 # Since: 2.5
 ##
 ##
 { 'struct': 'TlsCredsAnonProperties',
 { 'struct': 'TlsCredsAnonProperties',
   'base': 'TlsCredsProperties',
   'base': 'TlsCredsProperties',
-  'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] } } }
+  'data': { } }
 
 
 ##
 ##
 # @TlsCredsPskProperties:
 # @TlsCredsPskProperties:
 #
 #
 # Properties for tls-creds-psk objects.
 # Properties for tls-creds-psk objects.
 #
 #
-# @loaded: if true, the credentials are loaded immediately when
-#     applying this option and will ignore options that are processed
-#     later.  Don't use; only provided for compatibility.
-#     (default: false)
-#
 # @username: the username which will be sent to the server.  For
 # @username: the username which will be sent to the server.  For
 #     clients only.  If absent, "qemu" is sent and the property will
 #     clients only.  If absent, "qemu" is sent and the property will
 #     read back as an empty string.
 #     read back as an empty string.
 #
 #
-# Features:
-#
-# @deprecated: Member @loaded is deprecated.  Setting true doesn't
-#     make sense, and false is already the default.
-#
 # Since: 3.0
 # Since: 3.0
 ##
 ##
 { 'struct': 'TlsCredsPskProperties',
 { 'struct': 'TlsCredsPskProperties',
   'base': 'TlsCredsProperties',
   'base': 'TlsCredsProperties',
-  'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] },
-            '*username': 'str' } }
+  'data': { '*username': 'str' } }
 
 
 ##
 ##
 # @TlsCredsX509Properties:
 # @TlsCredsX509Properties:
 #
 #
 # Properties for tls-creds-x509 objects.
 # Properties for tls-creds-x509 objects.
 #
 #
-# @loaded: if true, the credentials are loaded immediately when
-#     applying this option and will ignore options that are processed
-#     later.  Don't use; only provided for compatibility.
-#     (default: false)
-#
 # @sanity-check: if true, perform some sanity checks before using the
 # @sanity-check: if true, perform some sanity checks before using the
 #     credentials (default: true)
 #     credentials (default: true)
 #
 #
@@ -573,17 +537,11 @@
 #     provides the ID of a previously created secret object containing
 #     provides the ID of a previously created secret object containing
 #     the password for decryption.
 #     the password for decryption.
 #
 #
-# Features:
-#
-# @deprecated: Member @loaded is deprecated.  Setting true doesn't
-#     make sense, and false is already the default.
-#
 # Since: 2.5
 # Since: 2.5
 ##
 ##
 { 'struct': 'TlsCredsX509Properties',
 { 'struct': 'TlsCredsX509Properties',
   'base': 'TlsCredsProperties',
   'base': 'TlsCredsProperties',
-  'data': { '*loaded': { 'type': 'bool', 'features': ['deprecated'] },
-            '*sanity-check': 'bool',
+  'data': { '*sanity-check': 'bool',
             '*passwordid': 'str' } }
             '*passwordid': 'str' } }
 ##
 ##
 # @QCryptoAkCipherAlgo:
 # @QCryptoAkCipherAlgo:

+ 16 - 0
tests/unit/test-crypto-hash.c

@@ -43,6 +43,9 @@
                       "63b54e4cb2d2032b393994aa263c0dbb" \
                       "63b54e4cb2d2032b393994aa263c0dbb" \
                       "e00a9f2fe9ef6037352232a1eec55ee7"
                       "e00a9f2fe9ef6037352232a1eec55ee7"
 #define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
 #define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
+#ifdef CONFIG_CRYPTO_SM3
+#define OUTPUT_SM3 "d4a97db105b477b84c4f20ec9c31a6c814e2705a0b83a5a89748d75f0ef456a1"
+#endif
 
 
 #define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
 #define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
 #define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
 #define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
@@ -55,6 +58,10 @@
                           "7sVe5w=="
                           "7sVe5w=="
 #define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
 #define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
 
 
+#ifdef CONFIG_CRYPTO_SM3
+#define OUTPUT_SM3_B64 "1Kl9sQW0d7hMTyDsnDGmyBTicFoLg6Wol0jXXw70VqE="
+#endif
+
 static const char *expected_outputs[] = {
 static const char *expected_outputs[] = {
     [QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5,
     [QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5,
     [QCRYPTO_HASH_ALGO_SHA1] = OUTPUT_SHA1,
     [QCRYPTO_HASH_ALGO_SHA1] = OUTPUT_SHA1,
@@ -63,6 +70,9 @@ static const char *expected_outputs[] = {
     [QCRYPTO_HASH_ALGO_SHA384] = OUTPUT_SHA384,
     [QCRYPTO_HASH_ALGO_SHA384] = OUTPUT_SHA384,
     [QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512,
     [QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160,
+#ifdef CONFIG_CRYPTO_SM3
+    [QCRYPTO_HASH_ALGO_SM3] = OUTPUT_SM3,
+#endif
 };
 };
 static const char *expected_outputs_b64[] = {
 static const char *expected_outputs_b64[] = {
     [QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5_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_SHA384] = OUTPUT_SHA384_B64,
     [QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512_B64,
     [QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512_B64,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160_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[] = {
 static const int expected_lens[] = {
     [QCRYPTO_HASH_ALGO_MD5] = 16,
     [QCRYPTO_HASH_ALGO_MD5] = 16,
@@ -81,6 +94,9 @@ static const int expected_lens[] = {
     [QCRYPTO_HASH_ALGO_SHA384] = 48,
     [QCRYPTO_HASH_ALGO_SHA384] = 48,
     [QCRYPTO_HASH_ALGO_SHA512] = 64,
     [QCRYPTO_HASH_ALGO_SHA512] = 64,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = 20,
     [QCRYPTO_HASH_ALGO_RIPEMD160] = 20,
+#ifdef CONFIG_CRYPTO_SM3
+    [QCRYPTO_HASH_ALGO_SM3] = 32,
+#endif
 };
 };
 
 
 static const char hex[] = "0123456789abcdef";
 static const char hex[] = "0123456789abcdef";

+ 8 - 0
tests/unit/test-crypto-hmac.c

@@ -76,6 +76,14 @@ static QCryptoHmacTestData test_data[] = {
             "94964ed4c1155b62b668c241d67279e5"
             "94964ed4c1155b62b668c241d67279e5"
             "8a711676",
             "8a711676",
     },
     },
+#ifdef CONFIG_CRYPTO_SM3
+    {
+        .alg = QCRYPTO_HASH_ALGO_SM3,
+        .hex_digest =
+            "760e3799332bc913819b930085360ddb"
+    "c05529261313d5b15b75bab4fd7ae91e",
+    },
+#endif
 };
 };
 
 
 static const char hex[] = "0123456789abcdef";
 static const char hex[] = "0123456789abcdef";

+ 16 - 0
tests/unit/test-crypto-pbkdf.c

@@ -325,6 +325,22 @@ static QCryptoPbkdfTestData test_data[] = {
                "\xce\xbf\x91\x14\x8b\x5c\x48\x41",
                "\xce\xbf\x91\x14\x8b\x5c\x48\x41",
         .nout = 32
         .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
 #if 0
     {
     {
         .path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",
         .path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",