static int x25519_mpi(unsigned char *q, const unsigned char *n, gcry_mpi_t mpi_p) { unsigned char priv_be[32]; unsigned char result_be[32]; size_t result_len = 0; gcry_mpi_t mpi = NULL; gcry_ctx_t ctx = NULL; gcry_mpi_point_t P = NULL; gcry_mpi_point_t Q = NULL; int r = -1; /* Default to infinity (all zeroes). */ memset(q, 0, 32); /* Keys are in little-endian, but gcry_mpi_scan expects big endian. Convert * keys and ensure that the result is a valid Curve25519 secret scalar. */ copy_and_reverse(priv_be, n, 32); priv_be[0] &= 127; priv_be[0] |= 64; priv_be[31] &= 248; gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, priv_be, 32, NULL); if (gcry_mpi_ec_new(&ctx, NULL, "Curve25519")) { /* Should not happen, possibly out-of-memory. */ goto leave; } /* Compute Q = nP */ Q = gcry_mpi_point_new(0); P = gcry_mpi_point_set(NULL, mpi_p, NULL, GCRYMPI_CONST_ONE); gcry_mpi_ec_mul(Q, mpi, P, ctx); /* Note: mpi is reused to store the result. */ if (gcry_mpi_ec_get_affine(mpi, NULL, Q, ctx)) { /* Infinity. */ goto leave; } if (gcry_mpi_print(GCRYMPI_FMT_USG, result_be, 32, &result_len, mpi)) { /* Should not happen, possibly out-of-memory. */ goto leave; } copy_and_reverse(q, result_be, result_len); r = 0; leave: gcry_mpi_point_release(P); gcry_mpi_point_release(Q); gcry_ctx_release(ctx); gcry_mpi_release(mpi); /* XXX erase priv_be and result_be */ return r; }
static void set_get_point (void) { gcry_mpi_point_t point; gcry_mpi_t x, y, z; wherestr = "set_get_point"; show ("checking point setting functions\n"); point = gcry_mpi_point_new (0); x = gcry_mpi_set_ui (NULL, 17); y = gcry_mpi_set_ui (NULL, 42); z = gcry_mpi_set_ui (NULL, 11371); gcry_mpi_point_get (x, y, z, point); if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0)) fail ("new point not initialized to (0,0,0)\n"); gcry_mpi_point_snatch_get (x, y, z, point); point = NULL; if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0)) fail ("snatch_get failed\n"); gcry_mpi_release (x); gcry_mpi_release (y); gcry_mpi_release (z); point = gcry_mpi_point_new (0); x = gcry_mpi_set_ui (NULL, 17); y = gcry_mpi_set_ui (NULL, 42); z = gcry_mpi_set_ui (NULL, 11371); gcry_mpi_point_set (point, x, y, z); gcry_mpi_set_ui (x, 23); gcry_mpi_set_ui (y, 24); gcry_mpi_set_ui (z, 25); gcry_mpi_point_get (x, y, z, point); if (gcry_mpi_cmp_ui (x, 17) || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371)) fail ("point_set/point_get failed\n"); gcry_mpi_point_snatch_set (point, x, y, z); x = gcry_mpi_new (0); y = gcry_mpi_new (0); z = gcry_mpi_new (0); gcry_mpi_point_get (x, y, z, point); if (gcry_mpi_cmp_ui (x, 17) || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371)) fail ("point_snatch_set/point_get failed\n"); gcry_mpi_point_release (point); gcry_mpi_release (x); gcry_mpi_release (y); gcry_mpi_release (z); }
void gotr_ecbd_gen_circle_key(gcry_mpi_point_t *ret, gcry_mpi_point_t *X, gcry_mpi_point_t Z, gcry_mpi_t r) { gcry_mpi_point_t tmp = gcry_mpi_point_new(0); gcry_mpi_t n = gcry_mpi_new(0); unsigned int i; gcry_mpi_point_release(*ret); *ret = gcry_mpi_point_set(NULL, NULL, GCRYMPI_CONST_ONE, GCRYMPI_CONST_ONE); for (i = 0; X[i]; i++) { gcry_mpi_set_ui(n, i+1); gcry_mpi_ec_mul(tmp, n, X[i], edctx); gcry_mpi_ec_add(*ret, *ret, tmp, edctx); } gcry_mpi_mul_ui(n, r, i+1); gcry_mpi_ec_mul(tmp, n, Z, edctx); gcry_mpi_ec_add(*ret, *ret, tmp, edctx); gcry_mpi_release(n); gcry_mpi_point_release(tmp); }
void gotr_ecbd_gen_X_value(gcry_mpi_point_t* ret, const gcry_mpi_point_t succ, const gcry_mpi_point_t pred, const gcry_mpi_t priv) { gcry_mpi_t x = gcry_mpi_new(0); gcry_mpi_t y = gcry_mpi_new(0); gcry_mpi_t z = gcry_mpi_new(0); gcry_mpi_point_t tmpoint = gcry_mpi_point_new(0); gotr_assert(succ && pred && priv); gcry_mpi_point_release(*ret); *ret = gcry_mpi_point_new(0); ///@todo use gcry_mpi_ec_sub after it is released gcry_mpi_point_get(x, y, z, pred); gcry_mpi_neg(x, x); gcry_mpi_point_set(tmpoint, x, y, z); gcry_mpi_ec_add(tmpoint, succ, tmpoint, edctx); gcry_mpi_ec_mul(*ret, priv, tmpoint, edctx); gcry_mpi_point_release(tmpoint); gcry_mpi_release(x); gcry_mpi_release(y); gcry_mpi_release(z); }
/* * Test iterative X25519 computation through lower layer MPI routines. * * Input: K (as hex string), ITER, R (as hex string) * * where R is expected result of iterating X25519 by ITER times. * */ static void test_it (int testno, const char *k_str, int iter, const char *result_str) { gcry_ctx_t ctx; gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_mpi_t mpi_k = NULL; gcry_mpi_t mpi_x = NULL; gcry_mpi_point_t P = NULL; gcry_mpi_point_t Q; int i; gcry_mpi_t mpi_kk = NULL; if (verbose > 1) info ("Running test %d: iteration=%d\n", testno, iter); gcry_mpi_ec_new (&ctx, NULL, "Curve25519"); Q = gcry_mpi_point_new (0); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error scanning MPI for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error scanning MPI for test %d, %s: %s", testno, "x", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE); mpi_k = gcry_mpi_copy (mpi_x); if (debug) print_mpi ("k", mpi_k); for (i = 0; i < iter; i++) { /* * Another variant of decodeScalar25519 thing. */ mpi_kk = gcry_mpi_set (mpi_kk, mpi_k); gcry_mpi_set_bit (mpi_kk, 254); gcry_mpi_clear_bit (mpi_kk, 255); gcry_mpi_clear_bit (mpi_kk, 0); gcry_mpi_clear_bit (mpi_kk, 1); gcry_mpi_clear_bit (mpi_kk, 2); gcry_mpi_ec_mul (Q, mpi_kk, P, ctx); P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE); gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx); if (debug) print_mpi ("k", mpi_k); } { unsigned char res[32]; char *r, *r0; gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k); reverse_buffer (res, 32); r0 = r = xmalloc (65); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=0; i < 32; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("curv25519 failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: gcry_mpi_release (mpi_kk); gcry_mpi_release (mpi_k); gcry_mpi_point_release (P); gcry_mpi_release (mpi_x); xfree (buffer); gcry_mpi_point_release (Q); gcry_ctx_release (ctx); }