Skip to content

Instantly share code, notes, and snippets.

@guidovranken
Created January 29, 2026 14:32
Show Gist options
  • Select an option

  • Save guidovranken/92222b4ed35041cd578ebea8e83892dd to your computer and use it in GitHub Desktop.

Select an option

Save guidovranken/92222b4ed35041cd578ebea8e83892dd to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <gcrypt.h>
int main(void) {
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
gcry_ctx_t ctx;
gcry_mpi_ec_new(&ctx, NULL, "sm2p256v1");
// Point with small X (1 limb), Z != 1
gcry_mpi_t X = gcry_mpi_set_ui(NULL, 9);
gcry_mpi_t Y, Z, scalar;
gcry_mpi_scan(&Y, GCRYMPI_FMT_HEX,
"3EE15EF0050F0FD70857D63C72B31A7066E9D02AEECCCE8B00D27AC9AC7A673A", 0, NULL);
Z = gcry_mpi_set_ui(NULL, 27);
scalar = gcry_mpi_set_ui(NULL, 27);
gcry_mpi_point_t P = gcry_mpi_point_new(0);
gcry_mpi_point_set(P, X, Y, Z);
gcry_mpi_point_t R1 = gcry_mpi_point_new(0);
gcry_mpi_ec_mul(R1, scalar, P, ctx);
gcry_mpi_point_set(P, X, Y, Z);
gcry_mpi_ec_curve_point(P, ctx); // BUG: corrupts P
gcry_mpi_point_t R2 = gcry_mpi_point_new(0);
gcry_mpi_ec_mul(R2, scalar, P, ctx);
gcry_mpi_t r1x = gcry_mpi_new(0), r2x = gcry_mpi_new(0);
gcry_mpi_ec_get_affine(r1x, NULL, R1, ctx);
gcry_mpi_ec_get_affine(r2x, NULL, R2, ctx);
unsigned char *buf;
size_t len;
printf("Test 1 (clean point): ");
gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, &len, r1x);
printf("x = %s\n", buf);
gcry_free(buf);
printf("Test 2 (after gcry_mpi_ec_curve_point): ");
gcry_mpi_aprint(GCRYMPI_FMT_HEX, &buf, &len, r2x);
printf("x = %s\n", buf);
gcry_free(buf);
if (gcry_mpi_cmp(r1x, r2x) == 0)
printf("PASS: results match\n");
else
printf("FAIL: results differ\n");
return gcry_mpi_cmp(r1x, r2x) != 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment