<div dir="ltr">#include <stdio.h><br>#include <gcrypt.h><br><br>int main(void) {<br>    gcry_control(GCRYCTL_DISABLE_SECMEM, 0);<br>    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);<br><br>    gcry_ctx_t ctx;<br>    gcry_mpi_ec_new(&ctx, NULL, "sm2p256v1");<br><br>    // Point with small X (1 limb), Z != 1<br>    gcry_mpi_t X = gcry_mpi_set_ui(NULL, 9);<br>    gcry_mpi_t Y, Z, scalar;<br>    gcry_mpi_scan(&Y, GCRYMPI_FMT_HEX,<br>        "3EE15EF0050F0FD70857D63C72B31A7066E9D02AEECCCE8B00D27AC9AC7A673A", 0, NULL);<br>    Z = gcry_mpi_set_ui(NULL, 27);<br>    scalar = gcry_mpi_set_ui(NULL, 27);<br><br>    gcry_mpi_point_t P = gcry_mpi_point_new(0);<br>    gcry_mpi_point_set(P, X, Y, Z);<br><br>    gcry_mpi_point_t R1 = gcry_mpi_point_new(0);<br>    gcry_mpi_ec_mul(R1, scalar, P, ctx);<br><br>    gcry_mpi_point_set(P, X, Y, Z);<br>    gcry_mpi_ec_curve_point(P, ctx);  // BUG: corrupts P<br><br>    gcry_mpi_point_t R2 = gcry_mpi_point_new(0);<br>    gcry_mpi_ec_mul(R2, scalar, P, ctx);<br><br>    gcry_mpi_t r1x = gcry_mpi_new(0), r2x = gcry_mpi_new(0);<br>    gcry_mpi_ec_get_affine(r1x, NULL, R1, ctx);<br>    gcry_mpi_ec_get_affine(r2x, NULL, R2, ctx);<br><br>    unsigned char *buf;<br>    size_t len;<br><br>    printf("Test 1 (clean point): ");<br>    gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, &len, r1x);<br>    printf("x = %s\n", buf);<br>    gcry_free(buf);<br><br>    printf("Test 2 (after gcry_mpi_ec_curve_point): ");<br>    gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, &len, r2x);<br>    printf("x = %s\n", buf);<br>    gcry_free(buf);<br><br>    if (gcry_mpi_cmp(r1x, r2x) == 0)<br>        printf("PASS: results match\n");<br>    else<br>        printf("FAIL: results differ\n");<br><br>    return gcry_mpi_cmp(r1x, r2x) != 0;<br>}<br><div><br></div><div>Afaik this affects Weierstrass curves with points satisfying Z >= 2 and limb count of X and/or Y != ctx->p->nlimbs. This is arguably a security vulnerability.</div><div><br></div><div>Guido</div></div>