summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-10-16 16:20:56 +0200
committerWerner Koch <wk@gnupg.org>2013-10-16 16:20:56 +0200
commita329b6abf00c990faf1986f9fbad7b4d71c13bcb (patch)
tree52b1f995cbc863404fb8a01005f3d17c29706655 /tests
parent45aa6131e93fac89d46733b3436d960f35fb99b2 (diff)
downloadlibgcrypt-a329b6abf00c990faf1986f9fbad7b4d71c13bcb.tar.gz
sexp: Add function gcry_sexp_extract_param.
* src/gcrypt.h.in (_GCRY_GCC_ATTR_SENTINEL): New. (gcry_sexp_extract_param): New. * src/visibility.c (gcry_sexp_extract_param): New. * src/visibility.h (gcry_sexp_extract_param): Add hack to detect internal use. * cipher/pubkey-util.c (_gcry_pk_util_extract_mpis): Move and split into ... * src/sexp.c (_gcry_sexp_vextract_param) (_gcry_sexp_extract_param): this. Change all callers. Add support for buffer descriptors and a path option/ * tests/tsexp.c (die, hex2buffer, hex2mpi, hex2mpiopa): New. (cmp_mpihex, cmp_bufhex): New. (check_extract_param): New. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/tsexp.c516
1 files changed, 513 insertions, 3 deletions
diff --git a/tests/tsexp.c b/tests/tsexp.c
index 7c4f7c81..8a6b9128 100644
--- a/tests/tsexp.c
+++ b/tests/tsexp.c
@@ -25,14 +25,48 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#include <assert.h>
#include "../src/gcrypt-int.h"
#define PGMNAME "tsexp"
+#ifndef DIM
+# define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#endif
+#define my_isascii(c) (!((c) & 0x80))
+#define digitp(p) (*(p) >= '0' && *(p) <= '9')
+#define hexdigitp(a) (digitp (a) \
+ || (*(a) >= 'A' && *(a) <= 'F') \
+ || (*(a) >= 'a' && *(a) <= 'f'))
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+#define xmalloc(a) gcry_xmalloc ((a))
+#define xcalloc(a,b) gcry_xcalloc ((a),(b))
+#define xstrdup(a) gcry_xstrdup ((a))
+#define xfree(a) gcry_free ((a))
+#define pass() do { ; } while (0)
+
+
static int verbose;
static int error_count;
static void
+die (const char *format, ...)
+{
+ va_list arg_ptr ;
+
+ fflush (stdout);
+ fprintf (stderr, "%s: ", PGMNAME);
+ va_start( arg_ptr, format ) ;
+ vfprintf (stderr, format, arg_ptr );
+ va_end(arg_ptr);
+ if (*format && format[strlen(format)-1] != '\n')
+ putc ('\n', stderr);
+ exit (1);
+}
+
+static void
info (const char *format, ...)
{
va_list arg_ptr;
@@ -42,6 +76,8 @@ info (const char *format, ...)
va_start( arg_ptr, format ) ;
vfprintf (stderr, format, arg_ptr );
va_end(arg_ptr);
+ if (*format && format[strlen(format)-1] != '\n')
+ putc ('\n', stderr);
}
}
@@ -54,10 +90,110 @@ fail ( const char *format, ... )
va_start( arg_ptr, format ) ;
vfprintf (stderr, format, arg_ptr );
va_end(arg_ptr);
+ if (*format && format[strlen(format)-1] != '\n')
+ putc ('\n', stderr);
error_count++;
}
+
+/* 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 gcry_mpi_t
+hex2mpi (const char *string)
+{
+ gpg_error_t err;
+ gcry_mpi_t val;
+
+ err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+ if (err)
+ die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
+ return val;
+}
+
+static gcry_mpi_t
+hex2mpiopa (const char *string)
+{
+ char *buffer;
+ size_t buflen;
+ gcry_mpi_t val;
+
+ buffer = hex2buffer (string, &buflen);
+ if (!buffer)
+ die ("hex2mpiopa '%s' failed: parser error\n", string);
+ val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
+ if (!buffer)
+ die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string);
+ return val;
+}
+
+
+/* Compare A to B, where B is given as a hex string. */
+static int
+cmp_mpihex (gcry_mpi_t a, const char *b)
+{
+ gcry_mpi_t bval;
+ int res;
+
+ if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+ bval = hex2mpiopa (b);
+ else
+ bval = hex2mpi (b);
+ res = gcry_mpi_cmp (a, bval);
+ gcry_mpi_release (bval);
+ return res;
+}
+
+/* Compare A to B, where A is a buffer and B a hex string. */
+static int
+cmp_bufhex (const void *a, size_t alen, const char *b)
+{
+ void *bbuf;
+ size_t blen;
+ int res;
+
+ if (!a && !b)
+ return 0;
+ if (a && !b)
+ return 1;
+ if (!a && b)
+ return -1;
+
+ bbuf = hex2buffer (b, &blen);
+ if (!bbuf)
+ die ("cmp_bufhex: error converting hex string\n");
+ if (alen != blen)
+ return alen < blen? -1 : 1;
+ res = memcmp (a, bbuf, alen);
+ xfree (bbuf);
+ return res;
+}
+
+
+
/* fixme: we need better tests */
static void
basic (void)
@@ -195,7 +331,7 @@ basic (void)
fail ("no car for `%s'\n", token);
continue;
}
- info ("car=`%.*s'\n", (int)n, p);
+ /* info ("car=`%.*s'\n", (int)n, p); */
s2 = gcry_sexp_cdr (s1);
if (!s2)
@@ -230,7 +366,7 @@ basic (void)
fail("no car for `%s'\n", parm );
continue;
}
- info ("car=`%.*s'\n", (int)n, p);
+ /* info ("car=`%.*s'\n", (int)n, p); */
p = gcry_sexp_nth_data (s2, 1, &n);
if (!p)
{
@@ -238,7 +374,7 @@ basic (void)
fail("no cdr for `%s'\n", parm );
continue;
}
- info ("cdr=`%.*s'\n", (int)n, p);
+ /* info ("cdr=`%.*s'\n", (int)n, p); */
a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
gcry_sexp_release (s2);
@@ -457,6 +593,379 @@ check_sscan (void)
}
+static void
+check_extract_param (void)
+{
+ /* This sample data is a real key but with some parameters of the
+ public key modified. */
+ static char sample1[] =
+ "(key-data"
+ " (public-key"
+ " (ecc"
+ " (curve Ed25519)"
+ " (p #6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
+ " (a #EF#)"
+ " (b #C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
+ " (g #14"
+ " 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
+ " 6666666666666666666666666666666666666666666666666666666666666658#)"
+ " (n #0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
+ " (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
+ "))"
+ " (private-key"
+ " (ecc"
+ " (curve Ed25519)"
+ " (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
+ " (a #FF#)"
+ " (b #D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
+ " (g #04"
+ " 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
+ " 6666666666666666666666666666666666666666666666666666666666666658#)"
+ " (n #1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
+ " (q #30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
+ " (d #56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276#)"
+ ")))";
+
+ static char sample1_p[] =
+ "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
+ static char sample1_px[] =
+ "6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
+ static char sample1_a[] = "FF";
+ static char sample1_ax[] = "EF";
+ static char sample1_b[] =
+ "D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
+ static char sample1_bx[] =
+ "C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
+ static char sample1_g[] =
+ "04"
+ "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
+ "6666666666666666666666666666666666666666666666666666666666666658";
+ static char sample1_gx[] =
+ "14"
+ "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
+ "6666666666666666666666666666666666666666666666666666666666666658";
+ static char sample1_n[] =
+ "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
+ static char sample1_nx[] =
+ "0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
+ static char sample1_q[] =
+ "30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
+ static char sample1_qx[] =
+ "20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
+ static char sample1_d[] =
+ "56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276";
+
+ static struct {
+ const char *sexp_str;
+ const char *path;
+ const char *list;
+ int nparam;
+ gpg_err_code_t expected_err;
+ const char *exp_p;
+ const char *exp_a;
+ const char *exp_b;
+ const char *exp_g;
+ const char *exp_n;
+ const char *exp_q;
+ const char *exp_d;
+ } tests[] = {
+ {
+ sample1,
+ NULL,
+ "pabgnqd", 6,
+ GPG_ERR_MISSING_VALUE,
+ },
+ {
+ sample1,
+ NULL,
+ "pabgnq", 7,
+ GPG_ERR_INV_ARG
+ },
+ {
+ sample1,
+ NULL,
+ "pabgnqd", 7,
+ 0,
+ sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
+ sample1_qx, sample1_d
+ },
+ {
+ sample1,
+ NULL,
+ "abg", 3,
+ 0,
+ sample1_ax, sample1_bx, sample1_gx
+ },
+ {
+ sample1,
+ NULL,
+ "x?abg", 4,
+ 0,
+ NULL, sample1_ax, sample1_bx, sample1_gx
+ },
+ {
+ sample1,
+ NULL,
+ "p?abg", 4,
+ GPG_ERR_USER_1,
+ NULL, sample1_ax, sample1_bx, sample1_gx
+ },
+ {
+ sample1,
+ NULL,
+ "pax?gnqd", 7,
+ 0,
+ sample1_px, sample1_ax, NULL, sample1_gx, sample1_nx,
+ sample1_qx, sample1_d
+ },
+ {
+ sample1,
+ "public-key",
+ "pabgnqd", 7,
+ GPG_ERR_NO_OBJ, /* d is not in public key. */
+ sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
+ sample1_qx, sample1_d
+ },
+ {
+ sample1,
+ "private-key",
+ "pabgnqd", 7,
+ 0,
+ sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
+ sample1_q, sample1_d
+ },
+ {
+ sample1,
+ "public-key!ecc",
+ "pabgnq", 6,
+ 0,
+ sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
+ sample1_qx
+ },
+ {
+ sample1,
+ "public-key!ecc!foo",
+ "pabgnq", 6,
+ GPG_ERR_NOT_FOUND
+ },
+ {
+ sample1,
+ "public-key!!ecc",
+ "pabgnq", 6,
+ GPG_ERR_NOT_FOUND
+ },
+ {
+ sample1,
+ "private-key",
+ "pa/bgnqd", 7,
+ 0,
+ sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
+ sample1_q, sample1_d
+ },
+ {
+ sample1,
+ "private-key",
+ "p-a+bgnqd", 7,
+ 0,
+ sample1_p, "-01", sample1_b, sample1_g, sample1_n,
+ sample1_q, sample1_d
+ },
+ {NULL}
+ };
+ int idx, i;
+ const char *paramstr;
+ int paramidx;
+ gpg_error_t err;
+ gcry_sexp_t sxp;
+ gcry_mpi_t mpis[7];
+ gcry_buffer_t ioarray[7];
+ char iobuffer[200];
+
+ info ("checking gcry_sexp_extract_param\n");
+ for (idx=0; tests[idx].sexp_str; idx++)
+ {
+ err = gcry_sexp_new (&sxp, tests[idx].sexp_str, 0, 1);
+ if (err)
+ die ("converting string to sexp failed: %s", gpg_strerror (err));
+
+ memset (mpis, 0, sizeof mpis);
+ switch (tests[idx].nparam)
+ {
+ case 0:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ NULL);
+ break;
+ case 1:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, NULL);
+ break;
+ case 2:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, mpis+1, NULL);
+ break;
+ case 3:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, mpis+1, mpis+2, NULL);
+ break;
+ case 4:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, mpis+1, mpis+2, mpis+3, NULL);
+ break;
+ case 5:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
+ NULL);
+ break;
+ case 6:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
+ mpis+5, NULL);
+ break;
+ case 7:
+ err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
+ mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
+ mpis+5, mpis+6, NULL);
+ break;
+ default:
+ die ("test %d: internal error", idx);
+ }
+
+ if (tests[idx].expected_err
+ && tests[idx].expected_err != GPG_ERR_USER_1)
+ {
+ if (tests[idx].expected_err != gpg_err_code (err))
+ fail ("gcry_sexp_extract_param test %d failed: "
+ "expected error '%s' - got '%s'", idx,
+ gpg_strerror (tests[idx].expected_err),gpg_strerror (err));
+
+ }
+ else if (err)
+ {
+ fail ("gcry_sexp_extract_param test %d failed: %s",
+ idx, gpg_strerror (err));
+ }
+ else /* No error - check the extracted values. */
+ {
+ for (paramidx=0; paramidx < DIM (mpis); paramidx++)
+ {
+ switch (paramidx)
+ {
+ case 0: paramstr = tests[idx].exp_p; break;
+ case 1: paramstr = tests[idx].exp_a; break;
+ case 2: paramstr = tests[idx].exp_b; break;
+ case 3: paramstr = tests[idx].exp_g; break;
+ case 4: paramstr = tests[idx].exp_n; break;
+ case 5: paramstr = tests[idx].exp_q; break;
+ case 6: paramstr = tests[idx].exp_d; break;
+ default:
+ die ("test %d: internal error: bad param %d",
+ idx, paramidx);
+ }
+
+ if (tests[idx].expected_err == GPG_ERR_USER_1
+ && mpis[paramidx] && !paramstr && paramidx == 0)
+ ; /* Okay Special case error for param 0. */
+ else if (!mpis[paramidx] && !paramstr)
+ ; /* Okay. */
+ else if (!mpis[paramidx] && paramstr)
+ fail ("test %d: value for param %d expected but not returned",
+ idx, paramidx);
+ else if (mpis[paramidx] && !paramstr)
+ fail ("test %d: value for param %d not expected",
+ idx, paramidx);
+ else if (cmp_mpihex (mpis[paramidx], paramstr))
+ {
+ fail ("test %d: param %d mismatch", idx, paramidx);
+ gcry_log_debug ("expected: %s\n", paramstr);
+ gcry_log_debugmpi (" got", mpis[paramidx]);
+ }
+ else if (tests[idx].expected_err && paramidx == 0)
+ fail ("test %d: param %d: expected error '%s' - got 'Success'",
+ idx, paramidx, gpg_strerror (tests[idx].expected_err));
+ }
+
+ }
+
+ for (i=0; i < DIM (mpis); i++)
+ gcry_mpi_release (mpis[i]);
+ gcry_sexp_release (sxp);
+ }
+
+ info ("checking gcry_sexp_extract_param/desc\n");
+
+ memset (ioarray, 0, sizeof ioarray);
+
+ err = gcry_sexp_new (&sxp, sample1, 0, 1);
+ if (err)
+ die ("converting string to sexp failed: %s", gpg_strerror (err));
+
+ ioarray[1].size = sizeof iobuffer;
+ ioarray[1].data = iobuffer;
+ ioarray[1].off = 0;
+ ioarray[2].size = sizeof iobuffer;
+ ioarray[2].data = iobuffer;
+ ioarray[2].off = 50;
+ assert (ioarray[2].off < sizeof iobuffer);
+ err = gcry_sexp_extract_param (sxp, "key-data!private-key", "&pab",
+ ioarray+0, ioarray+1, ioarray+2, NULL);
+ if (err)
+ fail ("gcry_sexp_extract_param with desc failed: %s", gpg_strerror (err));
+ else
+ {
+ if (!ioarray[0].data)
+ fail ("gcry_sexp_extract_param/desc failed: no P");
+ else if (ioarray[0].size != 32)
+ fail ("gcry_sexp_extract_param/desc failed: P has wrong size");
+ else if (ioarray[0].len != 32)
+ fail ("gcry_sexp_extract_param/desc failed: P has wrong length");
+ else if (ioarray[0].off)
+ fail ("gcry_sexp_extract_param/desc failed: P has OFF set");
+ else if (cmp_bufhex (ioarray[0].data, ioarray[0].len, sample1_p))
+ {
+ fail ("gcry_sexp_extract_param/desc failed: P mismatch");
+ gcry_log_debug ("expected: %s\n", sample1_p);
+ gcry_log_debughex (" got", ioarray[0].data, ioarray[0].len);
+ }
+
+ if (!ioarray[1].data)
+ fail ("gcry_sexp_extract_param/desc failed: A buffer lost");
+ else if (ioarray[1].size != sizeof iobuffer)
+ fail ("gcry_sexp_extract_param/desc failed: A size changed");
+ else if (ioarray[1].off != 0)
+ fail ("gcry_sexp_extract_param/desc failed: A off changed");
+ else if (ioarray[1].len != 1)
+ fail ("gcry_sexp_extract_param/desc failed: A has wrong length");
+ else if (cmp_bufhex (ioarray[1].data + ioarray[1].off, ioarray[1].len,
+ sample1_a))
+ {
+ fail ("gcry_sexp_extract_param/desc failed: A mismatch");
+ gcry_log_debug ("expected: %s\n", sample1_a);
+ gcry_log_debughex (" got",
+ ioarray[1].data + ioarray[1].off, ioarray[1].len);
+ }
+
+ if (!ioarray[2].data)
+ fail ("gcry_sexp_extract_param/desc failed: B buffer lost");
+ else if (ioarray[2].size != sizeof iobuffer)
+ fail ("gcry_sexp_extract_param/desc failed: B size changed");
+ else if (ioarray[2].off != 50)
+ fail ("gcry_sexp_extract_param/desc failed: B off changed");
+ else if (ioarray[2].len != 32)
+ fail ("gcry_sexp_extract_param/desc failed: B has wrong length");
+ else if (cmp_bufhex (ioarray[2].data + ioarray[2].off, ioarray[2].len,
+ sample1_b))
+ {
+ fail ("gcry_sexp_extract_param/desc failed: B mismatch");
+ gcry_log_debug ("expected: %s\n", sample1_b);
+ gcry_log_debughex (" got",
+ ioarray[2].data + ioarray[2].off, ioarray[2].len);
+ }
+
+ xfree (ioarray[0].data);
+ }
+
+ gcry_sexp_release (sxp);
+}
int
@@ -472,6 +981,7 @@ main (int argc, char **argv)
canon_len ();
back_and_forth ();
check_sscan ();
+ check_extract_param ();
return error_count? 1:0;
}