diff --git a/tests/t-convert.c b/tests/t-convert.c
index ec566777..121039c7 100644
--- a/tests/t-convert.c
+++ b/tests/t-convert.c
@@ -1,530 +1,534 @@
/* t-convert.c - Tests for mpi print and scna functions
* Copyright (C) 2013 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see .
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#define PGM "t-convert"
#include "t-common.h"
static void
showhex (const char *prefix, const void *buffer, size_t buflen)
{
const unsigned char *s;
if (!verbose)
return;
fprintf (stderr, "%s: %s ", PGM, prefix);
for (s= buffer; buflen; buflen--, s++)
fprintf (stderr, "%02x", *s);
putc ('\n', stderr);
}
/* Allocate a bit string consisting of '0' and '1' from the MPI A. Do
not return any leading zero bits. Caller needs to gcry_free the
result. */
static char *
mpi2bitstr_nlz (gcry_mpi_t a)
{
char *p, *buf;
size_t length = gcry_mpi_get_nbits (a);
if (!length)
{
buf = p = xmalloc (3);
*p++ = ' ';
*p++ = '0';
}
else
{
buf = p = xmalloc (length + 1 + 1);
*p++ = gcry_mpi_is_neg (a)? '-':' ';
while (length-- > 1)
*p++ = gcry_mpi_test_bit (a, length) ? '1':'0';
*p++ = gcry_mpi_test_bit (a, 0) ? '1':'0';
}
*p = 0;
return buf;
}
static void
showmpi (const char *prefix, gcry_mpi_t a)
{
char *bitstr;
if (!verbose)
return;
bitstr = mpi2bitstr_nlz (a);
fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr);
xfree (bitstr);
}
/* Check that mpi_print does not return a negative zero. */
static void
negative_zero (void)
{
gpg_error_t err;
gcry_mpi_t a;
char *buf;
void *bufaddr = &buf;
struct { const char *name; enum gcry_mpi_format format; } fmts[] =
{
{ "STD", GCRYMPI_FMT_STD },
{ "PGP", GCRYMPI_FMT_PGP },
{ "SSH", GCRYMPI_FMT_SSH },
{ "HEX", GCRYMPI_FMT_HEX },
{ "USG", GCRYMPI_FMT_USG },
{ NULL, 0 }
};
int i;
if (debug)
info ("negative zero printing\n");
a = gcry_mpi_new (0);
for (i=0; fmts[i].name; i++)
{
err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
if (err)
fail ("error printing a zero as %s: %s\n",
fmts[i].name,gpg_strerror (err) );
else
gcry_free (buf);
}
/* With the current version of libgcrypt the next two statements
should set a to -0. */
gcry_mpi_sub_ui (a, a, 1);
gcry_mpi_add_ui (a, a, 1);
for (i=0; fmts[i].name; i++)
{
err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
if (err)
fail ("error printing a negative zero as %s: %s\n",
fmts[i].name,gpg_strerror (err) );
else
gcry_free (buf);
}
gcry_mpi_release (a);
}
static void
check_formats (void)
{
static struct {
int value;
struct {
const char *hex;
size_t stdlen;
const char *std;
size_t sshlen;
const char *ssh;
size_t usglen;
const char *usg;
size_t pgplen;
const char *pgp;
} a;
} data[] = {
{ 0, { "00",
0, "",
4, "\x00\x00\x00\x00",
0, "",
2, "\x00\x00"}
},
{ 1, { "01",
1, "\x01",
5, "\x00\x00\x00\x01\x01",
1, "\x01",
3, "\x00\x01\x01" }
},
{ 2, { "02",
1, "\x02",
5, "\x00\x00\x00\x01\x02",
1, "\x02",
3, "\x00\x02\x02" }
},
{ 127, { "7F",
1, "\x7f",
5, "\x00\x00\x00\x01\x7f",
1, "\x7f",
3, "\x00\x07\x7f" }
},
{ 128, { "0080",
2, "\x00\x80",
6, "\x00\x00\x00\x02\x00\x80",
1, "\x80",
3, "\x00\x08\x80" }
},
{ 129, { "0081",
2, "\x00\x81",
6, "\x00\x00\x00\x02\x00\x81",
1, "\x81",
3, "\x00\x08\x81" }
},
{ 255, { "00FF",
2, "\x00\xff",
6, "\x00\x00\x00\x02\x00\xff",
1, "\xff",
3, "\x00\x08\xff" }
},
{ 256, { "0100",
2, "\x01\x00",
6, "\x00\x00\x00\x02\x01\x00",
2, "\x01\x00",
4, "\x00\x09\x01\x00" }
},
{ 257, { "0101",
2, "\x01\x01",
6, "\x00\x00\x00\x02\x01\x01",
2, "\x01\x01",
4, "\x00\x09\x01\x01" }
},
{ -1, { "-01",
1, "\xff",
5, "\x00\x00\x00\x01\xff",
1,"\x01" }
},
{ -2, { "-02",
1, "\xfe",
5, "\x00\x00\x00\x01\xfe",
1, "\x02" }
},
{ -127, { "-7F",
1, "\x81",
5, "\x00\x00\x00\x01\x81",
1, "\x7f" }
},
{ -128, { "-0080",
1, "\x80",
5, "\x00\x00\x00\x01\x80",
1, "\x80" }
},
{ -129, { "-0081",
2, "\xff\x7f",
6, "\x00\x00\x00\x02\xff\x7f",
1, "\x81" }
},
{ -255, { "-00FF",
2, "\xff\x01",
6, "\x00\x00\x00\x02\xff\x01",
1, "\xff" }
},
{ -256, { "-0100",
2, "\xff\x00",
6, "\x00\x00\x00\x02\xff\x00",
2, "\x01\x00" }
},
{ -257, { "-0101",
2, "\xfe\xff",
6, "\x00\x00\x00\x02\xfe\xff",
2, "\x01\x01" }
},
{ 65535, { "00FFFF",
3, "\x00\xff\xff",
7, "\x00\x00\x00\x03\x00\xff\xff",
2, "\xff\xff",
4, "\x00\x10\xff\xff" }
},
{ 65536, { "010000",
3, "\x01\00\x00",
7, "\x00\x00\x00\x03\x01\x00\x00",
3, "\x01\x00\x00",
5, "\x00\x11\x01\x00\x00 "}
},
{ 65537, { "010001",
3, "\x01\00\x01",
7, "\x00\x00\x00\x03\x01\x00\x01",
3, "\x01\x00\x01",
5, "\x00\x11\x01\x00\x01" }
},
{ -65537, { "-010001",
3, "\xfe\xff\xff",
7, "\x00\x00\x00\x03\xfe\xff\xff",
3, "\x01\x00\x01" }
},
{ -65536, { "-010000",
3, "\xff\x00\x00",
7, "\x00\x00\x00\x03\xff\x00\x00",
3, "\x01\x00\x00" }
},
{ -65535, { "-00FFFF",
3, "\xff\x00\x01",
7, "\x00\x00\x00\x03\xff\x00\x01",
2, "\xff\xff" }
}
};
gpg_error_t err;
gcry_mpi_t a, b;
char *buf;
void *bufaddr = &buf;
int idx;
size_t buflen;
a = gcry_mpi_new (0);
for (idx=0; idx < DIM(data); idx++)
{
if (debug)
info ("print test %d\n", data[idx].value);
if (data[idx].value < 0)
{
gcry_mpi_set_ui (a, -data[idx].value);
gcry_mpi_neg (a, a);
}
else
gcry_mpi_set_ui (a, data[idx].value);
err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
if (err)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "HEX", gpg_strerror (err));
else
{
if (strcmp (buf, data[idx].a.hex))
{
fail ("error printing value %d as %s: %s\n",
data[idx].value, "HEX", "wrong result");
info ("expected: '%s'\n", data[idx].a.hex);
info (" got: '%s'\n", buf);
}
gcry_free (buf);
}
err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
if (err)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "STD", gpg_strerror (err));
else
{
if (buflen != data[idx].a.stdlen
|| memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
{
fail ("error printing value %d as %s: %s\n",
data[idx].value, "STD", "wrong result");
showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
if (err)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "SSH", gpg_strerror (err));
else
{
if (buflen != data[idx].a.sshlen
|| memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
{
fail ("error printing value %d as %s: %s\n",
data[idx].value, "SSH", "wrong result");
showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
if (err)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "USG", gpg_strerror (err));
else
{
if (buflen != data[idx].a.usglen
|| memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
{
fail ("error printing value %d as %s: %s\n",
data[idx].value, "USG", "wrong result");
showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, bufaddr, &buflen, a);
if (gcry_mpi_is_neg (a))
{
if (gpg_err_code (err) != GPG_ERR_INV_ARG)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "PGP", "Expected error not returned");
}
else if (err)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "PGP", gpg_strerror (err));
else
{
if (buflen != data[idx].a.pgplen
|| memcmp (buf, data[idx].a.pgp, data[idx].a.pgplen))
{
fail ("error printing value %d as %s: %s\n",
data[idx].value, "PGP", "wrong result");
showhex ("expected:", data[idx].a.pgp, data[idx].a.pgplen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
}
/* Now for the other direction. */
for (idx=0; idx < DIM(data); idx++)
{
if (debug)
info ("scan test %d\n", data[idx].value);
if (data[idx].value < 0)
{
gcry_mpi_set_ui (a, -data[idx].value);
gcry_mpi_neg (a, a);
}
else
gcry_mpi_set_ui (a, data[idx].value);
err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
if (err)
fail ("error scanning value %d from %s: %s\n",
data[idx].value, "HEX", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b))
{
fail ("error scanning value %d from %s: %s\n",
data[idx].value, "HEX", "wrong result");
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
data[idx].a.std, data[idx].a.stdlen, &buflen);
if (err)
fail ("error scanning value %d as %s: %s\n",
data[idx].value, "STD", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
{
fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "STD", "wrong result", buflen);
+ data[idx].value, "STD", "wrong result",
+ (long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
err = gcry_mpi_scan (&b, GCRYMPI_FMT_SSH,
data[idx].a.ssh, data[idx].a.sshlen, &buflen);
if (err)
fail ("error scanning value %d as %s: %s\n",
data[idx].value, "SSH", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b) || data[idx].a.sshlen != buflen)
{
fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "SSH", "wrong result", buflen);
+ data[idx].value, "SSH", "wrong result",
+ (long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
err = gcry_mpi_scan (&b, GCRYMPI_FMT_USG,
data[idx].a.usg, data[idx].a.usglen, &buflen);
if (err)
fail ("error scanning value %d as %s: %s\n",
data[idx].value, "USG", gpg_strerror (err));
else
{
if (gcry_mpi_is_neg (a))
gcry_mpi_neg (b, b);
if (gcry_mpi_cmp (a, b) || data[idx].a.usglen != buflen)
{
fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "USG", "wrong result", buflen);
+ data[idx].value, "USG", "wrong result",
+ (long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
/* Negative values are not supported by PGP, thus we don't have
an samples. */
if (!gcry_mpi_is_neg (a))
{
err = gcry_mpi_scan (&b, GCRYMPI_FMT_PGP,
data[idx].a.pgp, data[idx].a.pgplen, &buflen);
if (err)
fail ("error scanning value %d as %s: %s\n",
data[idx].value, "PGP", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b) || data[idx].a.pgplen != buflen)
{
fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "PGP", "wrong result", buflen);
+ data[idx].value, "PGP", "wrong result",
+ (long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
}
}
gcry_mpi_release (a);
}
int
main (int argc, char **argv)
{
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
verbose = debug = 1;
if (!gcry_check_version (GCRYPT_VERSION))
die ("version mismatch\n");
xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
if (debug)
xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
negative_zero ();
check_formats ();
info ("All tests completed. Errors: %d\n", error_count);
return error_count ? 1 : 0;
}
diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c
index 2f59a890..73628a81 100644
--- a/tests/t-ed25519.c
+++ b/tests/t-ed25519.c
@@ -1,497 +1,497 @@
/* t-ed25519.c - Check the Ed25519 crypto
* Copyright (C) 2013 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see .
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include "stopwatch.h"
#define PGM "t-ed25519"
#include "t-common.h"
#define N_TESTS 1026
static int sign_with_pk;
static int no_verify;
static int custom_data_file;
static void
show_note (const char *format, ...)
{
va_list arg_ptr;
if (!verbose && getenv ("srcdir"))
fputs (" ", stderr); /* To align above "PASS: ". */
else
fprintf (stderr, "%s: ", PGM);
va_start (arg_ptr, format);
vfprintf (stderr, format, arg_ptr);
if (*format && format[strlen(format)-1] != '\n')
putc ('\n', stderr);
va_end (arg_ptr);
}
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
fprintf (stderr, "%s: ", PGM);
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
/* Prepend FNAME with the srcdir environment variable's value and
- retrun an allocated filename. */
+ * return an allocated filename. */
char *
prepend_srcdir (const char *fname)
{
static const char *srcdir;
char *result;
if (!srcdir && !(srcdir = getenv ("srcdir")))
srcdir = ".";
result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
strcpy (result, srcdir);
strcat (result, "/");
strcat (result, fname);
return result;
}
/* Read next line but skip over empty and comment lines. Caller must
xfree the result. */
static char *
read_textline (FILE *fp, int *lineno)
{
char line[4096];
char *p;
do
{
if (!fgets (line, sizeof line, fp))
{
if (feof (fp))
return NULL;
die ("error reading input line: %s\n", strerror (errno));
}
++*lineno;
p = strchr (line, '\n');
if (!p)
die ("input line %d not terminated or too long\n", *lineno);
*p = 0;
for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
*p = 0;
}
while (!*line || *line == '#');
/* if (debug) */
/* info ("read line: '%s'\n", line); */
return xstrdup (line);
}
/* Copy the data after the tag to BUFFER. BUFFER will be allocated as
needed. */
static void
copy_data (char **buffer, const char *line, int lineno)
{
const char *s;
xfree (*buffer);
*buffer = NULL;
s = strchr (line, ':');
if (!s)
{
fail ("syntax error at input line %d", lineno);
return;
}
for (s++; my_isascii (*s) && isspace (*s); s++)
;
*buffer = xstrdup (s);
}
/* Convert STRING consisting of hex characters into its binary
representation and return it as an allocated buffer. The valid
length of the buffer is returned at R_LENGTH. The string is
delimited by end of string. The function returns NULL on
error. */
static void *
hex2buffer (const char *string, size_t *r_length)
{
const char *s;
unsigned char *buffer;
size_t length;
buffer = xmalloc (strlen(string)/2+1);
length = 0;
for (s=string; *s; s +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
return NULL; /* Invalid hex digits. */
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static void
hexdowncase (char *string)
{
char *p;
for (p=string; *p; p++)
if (my_isascii (*p))
*p = tolower (*p);
}
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)
info ("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");
info (" expected: '%s'", sig);
info (" 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);
}
static void
check_ed25519 (const char *fname)
{
FILE *fp;
int lineno, ntests;
char *line;
int testno;
char *sk, *pk, *msg, *sig;
info ("Checking Ed25519.\n");
fp = fopen (fname, "r");
if (!fp)
die ("error opening '%s': %s\n", fname, strerror (errno));
testno = 0;
sk = pk = msg = sig = NULL;
lineno = ntests = 0;
while ((line = read_textline (fp, &lineno)))
{
if (!strncmp (line, "TST:", 4))
testno = atoi (line+4);
else if (!strncmp (line, "SK:", 3))
copy_data (&sk, line, lineno);
else if (!strncmp (line, "PK:", 3))
copy_data (&pk, line, lineno);
else if (!strncmp (line, "MSG:", 4))
copy_data (&msg, line, lineno);
else if (!strncmp (line, "SIG:", 4))
copy_data (&sig, line, lineno);
else
fail ("unknown tag at input line %d", lineno);
xfree (line);
if (testno && sk && pk && msg && sig)
{
hexdowncase (sig);
one_test (testno, sk, pk, msg, sig);
ntests++;
if (!(ntests % 256))
show_note ("%d of %d tests done\n", ntests, N_TESTS);
xfree (pk); pk = NULL;
xfree (sk); sk = NULL;
xfree (msg); msg = NULL;
xfree (sig); sig = NULL;
}
}
xfree (pk);
xfree (sk);
xfree (msg);
xfree (sig);
if (ntests != N_TESTS && !custom_data_file)
fail ("did %d tests but expected %d", ntests, N_TESTS);
else if ((ntests % 256))
show_note ("%d tests done\n", ntests);
fclose (fp);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
char *fname = NULL;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
fputs ("usage: " PGM " [options]\n"
"Options:\n"
" --verbose print timings etc.\n"
" --debug flyswatter\n"
" --sign-with-pk also use the public key for signing\n"
" --no-verify skip the verify test\n"
" --data FNAME take test data from file FNAME\n",
stdout);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--; argv++;
}
else if (!strcmp (*argv, "--sign-with-pk"))
{
sign_with_pk = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--no-verify"))
{
no_verify = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--data"))
{
argc--; argv++;
if (argc)
{
xfree (fname);
fname = xstrdup (*argv);
argc--; argv++;
}
}
else if (!strncmp (*argv, "--", 2))
die ("unknown option '%s'", *argv);
}
if (!fname)
fname = prepend_srcdir ("t-ed25519.inp");
else
custom_data_file = 1;
xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
if (!gcry_check_version (GCRYPT_VERSION))
die ("version mismatch\n");
if (debug)
xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
/* Ed25519 isn't supported in fips mode */
if (gcry_fips_mode_active())
return 77;
start_timer ();
check_ed25519 (fname);
stop_timer ();
xfree (fname);
info ("All tests completed in %s. Errors: %d\n",
elapsed_time (1), error_count);
return !!error_count;
}