summaryrefslogtreecommitdiff
path: root/tests/fipsdrv.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-10-02 19:30:08 +0000
committerWerner Koch <wk@gnupg.org>2008-10-02 19:30:08 +0000
commit0c72118b50098baca5267bc15a2fb2cb51a8cf65 (patch)
treeb16706b7005901975a3f7568d4969f0522a28256 /tests/fipsdrv.c
parente9c29dc331090fe9b92cca05b88a6aae6af478ea (diff)
downloadlibgcrypt-0c72118b50098baca5267bc15a2fb2cb51a8cf65.tar.gz
Add rsa verify function.
Diffstat (limited to 'tests/fipsdrv.c')
-rw-r--r--tests/fipsdrv.c192
1 files changed, 159 insertions, 33 deletions
diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c
index 25018808..68b48e9d 100644
--- a/tests/fipsdrv.c
+++ b/tests/fipsdrv.c
@@ -431,11 +431,11 @@ parse_tag (unsigned char const **buffer, size_t *buflen, struct tag_info *ti)
}
-/* Read the file FNAME assuming it is a PEM encoded private key file
- and return an S-expression. With SHOW set, the key parameters are
- printed. */
+/* Read the file FNAME assuming it is a PEM encoded private or public
+ key file and return an S-expression. With SHOW set, the key
+ parameters are printed. */
static gcry_sexp_t
-read_key_file (const char *fname, int show)
+read_key_file (const char *fname, int private, int show)
{
gcry_error_t err;
FILE *fp;
@@ -445,6 +445,7 @@ read_key_file (const char *fname, int show)
size_t derlen;
struct tag_info ti;
gcry_mpi_t keyparms[8];
+ int n_keyparms = private? 8 : 2;
int idx;
gcry_sexp_t s_key;
@@ -471,7 +472,7 @@ read_key_file (const char *fname, int show)
goto bad_asn1; /* The value of the first integer is no 0. */
der += ti.length; derlen += ti.length;
- for (idx=0; idx < DIM(keyparms); idx++)
+ for (idx=0; idx < n_keyparms; idx++)
{
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef)
@@ -489,28 +490,39 @@ read_key_file (const char *fname, int show)
die ("error scanning RSA parameter %d: %s\n", idx, gpg_strerror (err));
der += ti.length; derlen += ti.length;
}
- if (idx != DIM(keyparms))
+ if (idx != n_keyparms)
die ("not enough RSA key parameters\n");
gcry_free (buffer);
- /* Convert from OpenSSL parameter ordering to the OpenPGP order. */
- /* First check that p < q; if not swap p and q and recompute u. */
- if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0)
+ if (private)
{
- gcry_mpi_swap (keyparms[3], keyparms[4]);
- gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]);
+ /* Convert from OpenSSL parameter ordering to the OpenPGP order. */
+ /* First check that p < q; if not swap p and q and recompute u. */
+ if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0)
+ {
+ gcry_mpi_swap (keyparms[3], keyparms[4]);
+ gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]);
+ }
+
+ /* Build the S-expression. */
+ err = gcry_sexp_build (&s_key, NULL,
+ "(private-key(rsa(n%m)(e%m)"
+ /**/ "(d%m)(p%m)(q%m)(u%m)))",
+ keyparms[0], keyparms[1], keyparms[2],
+ keyparms[3], keyparms[4], keyparms[7] );
}
+ else
+ {
+ err = gcry_sexp_build (&s_key, NULL,
+ "(public-key(rsa(n%m)(e%m)))",
+ keyparms[0], keyparms[1]);
- /* Build the S-expression. */
- err = gcry_sexp_build (&s_key, NULL,
- "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
- keyparms[0], keyparms[1], keyparms[2],
- keyparms[3], keyparms[4], keyparms[7] );
+ }
if (err)
die ("error building S-expression: %s\n", gpg_strerror (err));
-
- for (idx=0; idx < DIM(keyparms); idx++)
+
+ for (idx=0; idx < n_keyparms; idx++)
gcry_mpi_release (keyparms[idx]);
return s_key;
@@ -521,6 +533,39 @@ read_key_file (const char *fname, int show)
}
+/* Read the file FNAME assuming it is a binary signature result and
+ return an an S-expression suitable for gcry_pk_verify. */
+static gcry_sexp_t
+read_sig_file (const char *fname)
+{
+ gcry_error_t err;
+ FILE *fp;
+ char *buffer;
+ size_t buflen;
+ gcry_mpi_t tmpmpi;
+ gcry_sexp_t s_sig;
+
+ fp = fopen (fname, "rb");
+ if (!fp)
+ die ("can't open `%s': %s\n", fname, strerror (errno));
+ buffer = read_file (fp, 0, &buflen);
+ if (!buffer)
+ die ("error reading `%s'\n", fname);
+ fclose (fp);
+
+ err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, buffer, buflen, NULL);
+ if (!err)
+ err = gcry_sexp_build (&s_sig, NULL,
+ "(sig-val(rsa(s %m)))", tmpmpi);
+ if (err)
+ die ("error building S-expression: %s\n", gpg_strerror (err));
+ gcry_mpi_release (tmpmpi);
+ gcry_free (buffer);
+
+ return s_sig;
+}
+
+
static void
print_buffer (const void *buffer, size_t length)
{
@@ -1038,12 +1083,12 @@ run_rsa_sign (const void *data, size_t datalen,
die ("gcry_sexp_build failed for RSA data input: %s\n",
gpg_strerror (err));
- s_key = read_key_file (keyfile, 0);
+ s_key = read_key_file (keyfile, 1, 0);
err = gcry_pk_sign (&s_sig, s_data, s_key);
if (err)
{
- gcry_sexp_release (read_key_file (keyfile, 1));
+ gcry_sexp_release (read_key_file (keyfile, 1, 1));
die ("gcry_pk_signed failed (datalen=%d,keyfile=%s): %s\n",
(int)datalen, keyfile, gpg_strerror (err));
}
@@ -1083,6 +1128,56 @@ run_rsa_sign (const void *data, size_t datalen,
}
+
+/* Verify DATA of length DATALEN using the public key taken from the
+ PEM encoded KEYFILE and the hash algorithm HASHALGO against the
+ binary signature in SIGFILE. */
+static void
+run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1,
+ const char *keyfile, const char *sigfile)
+
+{
+ gpg_error_t err;
+ gcry_sexp_t s_data, s_key, s_sig;
+
+ if (pkcs1)
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags pkcs1)(hash %s %b))",
+ gcry_md_algo_name (hashalgo), (int)datalen, data);
+ else
+ {
+ gcry_mpi_t tmp;
+
+ err = gcry_mpi_scan (&tmp, GCRYMPI_FMT_USG, data, datalen,NULL);
+ if (!err)
+ {
+ err = gcry_sexp_build (&s_data, NULL,
+ "(data (flags raw)(value %m))", tmp);
+ gcry_mpi_release (tmp);
+ }
+ }
+ if (err)
+ die ("gcry_sexp_build failed for RSA data input: %s\n",
+ gpg_strerror (err));
+
+ s_key = read_key_file (keyfile, 0, 0);
+
+ s_sig = read_sig_file (sigfile);
+
+ err = gcry_pk_verify (s_sig, s_data, s_key);
+ if (!err)
+ puts ("GOOD signature\n");
+ else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE)
+ puts ("BAD signature\n");
+ else
+ printf ("ERROR (%s)\n", gpg_strerror (err));
+
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_key);
+ gcry_sexp_release (s_data);
+}
+
+
static void
@@ -1100,19 +1195,20 @@ usage (int show_help)
"MODE:\n"
" encrypt, decrypt, digest, random, hmac-sha, rsa-{gen,sign,verify}\n"
"OPTIONS:\n"
- " --verbose print additional information\n"
- " --binary input and output is in binary form\n"
- " --no-fips do not force FIPS mode\n"
- " --key KEY use the hex encoded KEY\n"
- " --iv IV use the hex encoded IV\n"
- " --dt DT use the hex encoded DT for the RNG\n"
- " --algo NAME use algorithm NAME\n"
- " --keysize N use a keysize of N bits\n"
- " --chunk N read in chunks of N bytes (implies --binary)\n"
- " --pkcs1 use PKCS#1 encoding\n"
- " --loop enable random loop mode\n"
- " --progress print pogress indicators\n"
- " --help print this text\n"
+ " --verbose print additional information\n"
+ " --binary input and output is in binary form\n"
+ " --no-fips do not force FIPS mode\n"
+ " --key KEY use the hex encoded KEY\n"
+ " --iv IV use the hex encoded IV\n"
+ " --dt DT use the hex encoded DT for the RNG\n"
+ " --algo NAME use algorithm NAME\n"
+ " --keysize N use a keysize of N bits\n"
+ " --signature NAME take signature from file NAME\n"
+ " --chunk N read in chunks of N bytes (implies --binary)\n"
+ " --pkcs1 use PKCS#1 encoding\n"
+ " --loop enable random loop mode\n"
+ " --progress print pogress indicators\n"
+ " --help print this text\n"
"With no FILE, or when FILE is -, read standard input.\n"
"Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout);
exit (0);
@@ -1132,6 +1228,7 @@ main (int argc, char **argv)
const char *dt_string = NULL;
const char *algo_string = NULL;
const char *keysize_string = NULL;
+ const char *signature_string = NULL;
FILE *input;
void *data;
size_t datalen;
@@ -1223,6 +1320,14 @@ main (int argc, char **argv)
keysize_string = *argv;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--signature"))
+ {
+ argc--; argv++;
+ if (!argc)
+ usage (0);
+ signature_string = *argv;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--chunk"))
{
argc--; argv++;
@@ -1438,6 +1543,27 @@ main (int argc, char **argv)
}
else if (!strcmp (mode_string, "rsa-verify"))
{
+ int algo;
+
+ if (!key_string)
+ die ("option --key is required in this mode\n");
+ if (access (key_string, R_OK))
+ die ("option --key needs to specify an existing keyfile\n");
+ if (!algo_string)
+ die ("option --algo is required in this mode\n");
+ algo = gcry_md_map_name (algo_string);
+ if (!algo)
+ die ("digest algorithm `%s' is not supported\n", algo_string);
+ if (!data)
+ die ("no data available (do not use --chunk)\n");
+ if (!signature_string)
+ die ("option --signature is required in this mode\n");
+ if (access (signature_string, R_OK))
+ die ("option --signature needs to specify an existing file\n");
+
+ run_rsa_verify (data, datalen, algo, use_pkcs1, key_string,
+ signature_string);
+
}
else
usage (0);