static void one_test (int testno, const char *sk, const char *pk, const char *msg, const char *sig) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; size_t buflen, buflen2; gcry_sexp_t s_tmp, s_tmp2; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_msg= NULL; gcry_sexp_t s_sig= NULL; unsigned char *sig_r = NULL; unsigned char *sig_s = NULL; char *sig_rs_string = NULL; size_t sig_r_len, sig_s_len; if (verbose > 1) show ("Running test %d\n", testno); if (!(buffer = hex2buffer (sk, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (pk, &buflen2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", "invalid hex string"); goto leave; } if (sign_with_pk) err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (q %b)" " (d %b)))", (int)buflen2, buffer2, (int)buflen, buffer); else err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (d %b)))", (int)buflen, buffer); if (err) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (q %b)))", (int)buflen2, buffer2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", "invalid hex string"); goto leave; } if ((err = gcry_sexp_build (&s_msg, NULL, "(data" " (flags eddsa)" " (hash-algo sha512)" " (value %b))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", gpg_strerror (err)); goto leave; } if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk))) fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); if (debug) show_sexp ("sig=", s_sig); s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { sig_r = gcry_sexp_nth_buffer (s_tmp, 1, &sig_r_len); gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { sig_s = gcry_sexp_nth_buffer (s_tmp, 1, &sig_s_len); gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); s_tmp2 = NULL; if (!sig_r || !sig_s) fail ("gcry_pk_sign failed for test %d: %s", testno, "r or s missing"); else { sig_rs_string = xmalloc (2*(sig_r_len + sig_s_len)+1); p = sig_rs_string; *p = 0; for (i=0; i < sig_r_len; i++, p += 2) snprintf (p, 3, "%02x", sig_r[i]); for (i=0; i < sig_s_len; i++, p += 2) snprintf (p, 3, "%02x", sig_s[i]); if (strcmp (sig_rs_string, sig)) { fail ("gcry_pk_sign failed for test %d: %s", testno, "wrong value returned"); show (" expected: '%s'", sig); show (" got: '%s'", sig_rs_string); } } if (!no_verify) if ((err = gcry_pk_verify (s_sig, s_msg, s_pk))) fail ("gcry_pk_verify failed for test %d: %s", testno, gpg_strerror (err)); leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); gcry_sexp_release (s_msg); xfree (buffer); xfree (buffer2); xfree (sig_r); xfree (sig_s); xfree (sig_rs_string); }
/* * Test X25519 functionality through higher layer crypto routines. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X25519 (K, U). * * It calls gcry_pk_decrypt with Curve25519 private key and let * it compute X25519. */ static void test_cv (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_sexp_t s_pk = NULL; gcry_mpi_t mpi_k = NULL; gcry_sexp_t s_data = NULL; gcry_sexp_t s_result = NULL; gcry_sexp_t s_tmp = NULL; unsigned char *res = NULL; size_t res_len; if (verbose > 1) info ("Running test %d\n", testno); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k))) { fail ("error building s-exp for test %d, %s: %s", testno, "data", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } /* * The procedure of decodeUCoordinate will be done internally * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian * binary to build S-exp. * * We could add the prefix 0x40, but libgcrypt also supports * format with no prefix. So, it is OK not to put the prefix. */ if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Curve25519\")" " (flags djb-tweak)" " (q%b)))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, gpg_strerror (err)); s_tmp = gcry_sexp_find_token (s_result, "s", 0); if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value"); else { char *r, *r0; int i; /* To skip the prefix 0x40, for-loop start with i=1 */ r0 = r = xmalloc (2*(res_len)+1); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=1; i < res_len; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("gcry_pk_encrypt failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: xfree (res); gcry_mpi_release (mpi_k); gcry_sexp_release (s_tmp); gcry_sexp_release (s_result); gcry_sexp_release (s_data); gcry_sexp_release (s_pk); xfree (buffer); }