Commit 5bb5b7aeb9 for openssl.org

commit 5bb5b7aeb93d6f3cbf4981f54f88612fe6a82368
Author: Igor Ustinov <igus@openssl.foundation>
Date:   Mon Aug 3 15:16:47 2026 +0200

    Cover the SM2 scalar multiplication under ct-validation

    Assisted-by: Claude:claude-opus-4-8
    Reviewed-by: Alicja Kario <hkario@redhat.com>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Merge-date: Tue Sep 29 10:35:47 2026

diff --git a/.github/workflows/ct-validation-daily.yml b/.github/workflows/ct-validation-daily.yml
index 4d88dfc9cf..027e2054a8 100644
--- a/.github/workflows/ct-validation-daily.yml
+++ b/.github/workflows/ct-validation-daily.yml
@@ -80,7 +80,7 @@ jobs:
   ct-validation:
     needs: [validate-dispatch-inputs]
     if: |
-      github.repository == 'openssl/openssl' &&
+      (github.repository == 'openssl/openssl' || github.event_name == 'workflow_dispatch') &&
       !cancelled() &&
       (needs.validate-dispatch-inputs.result == 'success' || needs.validate-dispatch-inputs.result == 'skipped')
     strategy:
@@ -141,6 +141,7 @@ jobs:
         # - memcmp: test_crypto_memcmp
         # - ML-KEM: test_internal_ml_kem
         # - ML-DSA: test_internal_ml_dsa
+        # - SM2/EC: test_ec
         #
         # Also covered:
         # - test_ct_validation_helpers: The Valgrind-based constant-time
diff --git a/crypto/ec/ecp_sm2p256.c b/crypto/ec/ecp_sm2p256.c
index 517a43987f..2ba2279886 100644
--- a/crypto/ec/ecp_sm2p256.c
+++ b/crypto/ec/ecp_sm2p256.c
@@ -565,6 +565,13 @@ static int ecp_sm2p256_windowed_mul(const EC_GROUP *group,
             goto err;
         }

+        /*
+         * The scalar is secret (e.g. the SM2 decryption private key). Mark it
+         * so that under enable-ct-validation Valgrind flags any branch or
+         * memory index depending on it inside the scalar multiplication below.
+         */
+        CONSTTIME_SECRET(k, sizeof(k));
+
         ecp_sm2p256_point_get_affine(&t.a, &p.p);
         ecp_sm2p256_point_P_mul_by_scalar(&kP, k, t.a);
         ecp_sm2p256_point_add(r, r, &kP);
@@ -610,6 +617,13 @@ static int ecp_sm2p256_points_mul(const EC_GROUP *group,
             ECerr(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE);
             goto err;
         }
+
+        /*
+         * The generator scalar is secret (e.g. the SM2 signature nonce k).
+         * Mark it so that under enable-ct-validation any branch or memory
+         * index depending on it in [k]G is flagged by Valgrind.
+         */
+        CONSTTIME_SECRET(k, sizeof(k));
 #if !defined(OPENSSL_NO_SM2_PRECOMP)
         if (ecp_sm2p256_is_affine_G(generator)) {
             ecp_sm2p256_point_G_mul_by_scalar(&p.p, k);
@@ -645,6 +659,16 @@ static int ecp_sm2p256_points_mul(const EC_GROUP *group,
             ecp_sm2p256_point_add(&p.p, &p.p, out);
     }

+    /*
+     * The result ([k]G, or [d]C) is public. Declassify it so that the
+     * (legitimately variable-time) serialisation below and the branches the
+     * caller performs on the public signature/ciphertext do not trip
+     * ct-validation.
+     */
+    CONSTTIME_DECLASSIFY(p.p.X, sizeof(p.p.X));
+    CONSTTIME_DECLASSIFY(p.p.Y, sizeof(p.p.Y));
+    CONSTTIME_DECLASSIFY(p.p.Z, sizeof(p.p.Z));
+
     /* Not constant-time, but we're only operating on the public output. */
     if (!bn_set_words(r->X, p.p.X, P256_LIMBS)
         || !bn_set_words(r->Y, p.p.Y, P256_LIMBS)