/* This is the same as basic_ec_math but uses more advanced features. */ static void basic_ec_math_simplified (void) { gpg_error_t err; gcry_ctx_t ctx; gcry_mpi_point_t G, Q; gcry_mpi_t d; gcry_mpi_t x, y, z; gcry_sexp_t sexp; wherestr = "basic_ec_math_simplified"; show ("checking basic math functions for EC (variant)\n"); d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D"); Q = gcry_mpi_point_new (0); err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192"); if (err) die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err)); G = gcry_mpi_ec_get_point ("g", ctx, 1); if (!G) die ("gcry_mpi_ec_get_point(G) failed\n"); gcry_mpi_ec_mul (Q, d, G, ctx); x = gcry_mpi_new (0); y = gcry_mpi_new (0); z = gcry_mpi_new (0); gcry_mpi_point_get (x, y, z, Q); if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66") || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8") || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F")) fail ("computed public key does not match\n"); if (debug) { print_mpi ("Q.x", x); print_mpi ("Q.y", y); print_mpi ("Q.z", z); } if (gcry_mpi_ec_get_affine (x, y, Q, ctx)) fail ("failed to get affine coordinates\n"); if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE") || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966")) fail ("computed affine coordinates of public key do not match\n"); if (debug) { print_mpi ("q.x", x); print_mpi ("q.y", y); } gcry_mpi_release (z); gcry_mpi_release (y); gcry_mpi_release (x); /* Let us also check wheer we can update the context. */ err = gcry_mpi_ec_set_point ("g", G, ctx); if (err) die ("gcry_mpi_ec_set_point(G) failed\n"); err = gcry_mpi_ec_set_mpi ("d", d, ctx); if (err) die ("gcry_mpi_ec_set_mpi(d) failed\n"); /* FIXME: Below we need to check that the returned S-expression is as requested. For now we use manual inspection using --debug. */ /* Does get_sexp return the private key? */ err = gcry_pubkey_get_sexp (&sexp, 0, ctx); if (err) fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err)); else if (verbose) print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp); gcry_sexp_release (sexp); /* Does get_sexp return the public key if requested? */ err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx); if (err) fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err)); else if (verbose) print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp); gcry_sexp_release (sexp); /* Does get_sexp return the public key if after d has been deleted? */ err = gcry_mpi_ec_set_mpi ("d", NULL, ctx); if (err) die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n"); err = gcry_pubkey_get_sexp (&sexp, 0, ctx); if (err) fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err)); else if (verbose) print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp); gcry_sexp_release (sexp); /* Does get_sexp return an error after d has been deleted? */ err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx); if (gpg_err_code (err) != GPG_ERR_NO_SECKEY) fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n", gpg_strerror (err)); gcry_sexp_release (sexp); /* Does get_sexp return an error after d and Q have been deleted? */ err = gcry_mpi_ec_set_point ("q", NULL, ctx); if (err) die ("gcry_mpi_ec_set_point(q=NULL) failed\n"); err = gcry_pubkey_get_sexp (&sexp, 0, ctx); if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX) fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n", gpg_strerror (err)); gcry_sexp_release (sexp); gcry_mpi_point_release (Q); gcry_mpi_release (d); gcry_mpi_point_release (G); gcry_ctx_release (ctx); }
static void context_param (void) { gpg_error_t err; int idx; gcry_ctx_t ctx = NULL; gcry_mpi_t q, d; gcry_sexp_t keyparam; wherestr = "context_param"; show ("checking standard curves\n"); for (idx=0; test_curve[idx].desc; idx++) { gcry_ctx_release (ctx); err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc); if (err) { fail ("can't create context for curve '%s': %s\n", test_curve[idx].desc, gpg_strerror (err)); continue; } if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx)) continue; if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx)) continue; if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx)) continue; if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx)) continue; if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx)) continue; if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx)) continue; if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y, test_curve[idx].desc, ctx)) continue; if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx)) continue; } show ("checking sample public key (nistp256)\n"); q = hex2mpi (sample_p256_q); err = gcry_sexp_build (&keyparam, NULL, "(public-key(ecc(curve %s)(q %m)))", "NIST P-256", q); if (err) die ("gcry_sexp_build failed: %s\n", gpg_strerror (err)); gcry_mpi_release (q); /* We can't call gcry_pk_testkey because it is only implemented for private keys. */ /* err = gcry_pk_testkey (keyparam); */ /* if (err) */ /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */ /* gpg_strerror (err)); */ gcry_ctx_release (ctx); err = gcry_mpi_ec_new (&ctx, keyparam, NULL); if (err) fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n", gpg_strerror (err)); else { gcry_sexp_t sexp; get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx); get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256", ctx); /* Delete Q. */ err = gcry_mpi_ec_set_mpi ("q", NULL, ctx); if (err) fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err)); if (gcry_mpi_ec_get_mpi ("q", ctx, 0)) fail ("clearing Q for nistp256 did not work\n"); /* Set Q again. */ q = hex2mpi (sample_p256_q); err = gcry_mpi_ec_set_mpi ("q", q, ctx); if (err) fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err)); get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx); gcry_mpi_release (q); /* Get as s-expression. */ err = gcry_pubkey_get_sexp (&sexp, 0, ctx); if (err) fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err)); else if (debug) print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp); gcry_sexp_release (sexp); err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx); if (err) fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err)); else if (debug) print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp); gcry_sexp_release (sexp); err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx); if (gpg_err_code (err) != GPG_ERR_NO_SECKEY) fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n", gpg_strerror (err)); gcry_sexp_release (sexp); } show ("checking sample public key (Ed25519)\n"); q = hex2mpi (sample_ed25519_q); gcry_sexp_release (keyparam); err = gcry_sexp_build (&keyparam, NULL, "(public-key(ecc(curve %s)(flags eddsa)(q %m)))", "Ed25519", q); if (err) die ("gcry_sexp_build failed: %s\n", gpg_strerror (err)); gcry_mpi_release (q); /* We can't call gcry_pk_testkey because it is only implemented for private keys. */ /* err = gcry_pk_testkey (keyparam); */ /* if (err) */ /* fail ("gcry_pk_testkey failed for sample public key: %s\n", */ /* gpg_strerror (err)); */ gcry_ctx_release (ctx); err = gcry_mpi_ec_new (&ctx, keyparam, NULL); if (err) fail ("gcry_mpi_ec_new failed for sample public key: %s\n", gpg_strerror (err)); else { gcry_sexp_t sexp; get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx); get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y, "Ed25519", ctx); get_and_cmp_mpi ("q@eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx); /* Set d to see whether Q is correctly re-computed. */ d = hex2mpi (sample_ed25519_d); err = gcry_mpi_ec_set_mpi ("d", d, ctx); if (err) fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err)); gcry_mpi_release (d); get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx); /* Delete Q by setting d and then clearing d. The clearing is required so that we can check whether Q has been cleared and because further tests only expect a public key. */ d = hex2mpi (sample_ed25519_d); err = gcry_mpi_ec_set_mpi ("d", d, ctx); if (err) fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err)); gcry_mpi_release (d); err = gcry_mpi_ec_set_mpi ("d", NULL, ctx); if (err) fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err)); if (gcry_mpi_ec_get_mpi ("q", ctx, 0)) fail ("setting d for Ed25519 did not reset Q\n"); /* Set Q again. We need to use an opaque MPI here because sample_ed25519_q is in uncompressed format which can only be auto-detected if passed opaque. */ q = hex2mpiopa (sample_ed25519_q); err = gcry_mpi_ec_set_mpi ("q", q, ctx); if (err) fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err)); gcry_mpi_release (q); get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx); /* Get as s-expression. */ err = gcry_pubkey_get_sexp (&sexp, 0, ctx); if (err) fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err)); else if (debug) print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp); gcry_sexp_release (sexp); err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx); if (err) fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err)); else if (debug) print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp); gcry_sexp_release (sexp); err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx); if (gpg_err_code (err) != GPG_ERR_NO_SECKEY) fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n", gpg_strerror (err)); gcry_sexp_release (sexp); } gcry_ctx_release (ctx); gcry_sexp_release (keyparam); }