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)