summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-04-09 20:08:19 +0200
committerWerner Koch <wk@gnupg.org>2020-04-09 20:09:03 +0200
commit60c179b59e538aebb3a5f7621d92eee60b90c785 (patch)
tree287f4fd6fc3ac1321e2490638fc46f1147dadb72
parent1250a9cd859d99f487ca8d76a98d70d464324bbe (diff)
downloadlibgcrypt-60c179b59e538aebb3a5f7621d92eee60b90c785.tar.gz
sexp: Extend gcry_sexp_extract_param with new format specifiers.
* src/sexp.c (_gcry_sexp_vextract_param): Add new conversion methods. * tests/t-sexp.c (check_extract_param): Add corresponding tests. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--NEWS8
-rw-r--r--doc/gcrypt.texi21
-rw-r--r--src/sexp.c165
-rw-r--r--tests/t-sexp.c100
4 files changed, 268 insertions, 26 deletions
diff --git a/NEWS b/NEWS
index aa58fda8..264f34f1 100644
--- a/NEWS
+++ b/NEWS
@@ -41,10 +41,18 @@ Noteworthy changes in version 1.9.0 (unreleased) [C22/A3/R0]
- Fix fatal out of secure memory status in the s-expression parser
on heavy loaded systems. [also in 1.8.2]
+ * Extended interfaces:
+
+ - gcry_sexp_extract_param understands new format specifiers to
+ directly store to integers and strings.
+
+
* Interface changes relative to the 1.8.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_mpi_get_ui NEW function.
GCRYCTL_AUTO_EXPAND_SECMEM NEW control code.
+ gcry_sexp_extract_param EXTENDED.
+
* Release dates of 1.8.x versions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index d3142d07..fad1dfea 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4513,7 +4513,7 @@ likely want to use @code{GCRYMPI_FMT_USG}.
Extract parameters from an S-expression using a list of parameter
names. The names of these parameters are specified in LIST. White
space between the parameter names are ignored. Some special characters
-may be given to control the conversion:
+and character sequences may be given to control the conversion:
@table @samp
@item +
@@ -4526,6 +4526,25 @@ Switch to opaque MPI format. The resulting MPIs may not be used for
computations; see @code{gcry_mpi_get_opaque} for details.
@item &
Switch to buffer descriptor mode. See below for details.
+@item %s
+Switch to string mode. The expected argument is the address of a
+@code{char *} variable; the caller must release that value. If the
+parameter was marked optional and is not found, NULL is stored.
+@item %u
+Switch to unsigned integer mode. The expected argument is address of
+a @code{unsigned int} variable.
+@item %lu
+Switch to unsigned long integer mode. The expected argument is address of
+a @code{unsigned long} variable.
+@item %d
+Switch to signed integer mode. The expected argument is address of
+a @code{int} variable.
+@item %ld
+Switch to signed long integer mode. The expected argument is address of
+a @code{long} variable.
+@item %zu
+Switch to size_t mode. The expected argument is address of
+a @code{size_t} variable.
@item ?
If immediately following a parameter letter (no white space allowed),
that parameter is considered optional.
diff --git a/src/sexp.c b/src/sexp.c
index 17341ba5..4697f77e 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -2246,11 +2246,17 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
* names of these parameters are given by the string LIST. Some
* special characters may be given to control the conversion:
*
- * + :: Switch to unsigned integer format (default).
- * - :: Switch to standard signed format.
- * / :: Switch to opaque format.
- * & :: Switch to buffer descriptor mode - see below.
- * ? :: The previous parameter is optional.
+ * + :: Switch to unsigned integer format (default).
+ * - :: Switch to standard signed format.
+ * / :: Switch to opaque format
+ * & :: Switch to buffer descriptor mode - see below.
+ * %s :: Switch to allocated string arguments.
+ * %u :: Switch to unsigned integer arguments.
+ * %lu :: Switch to unsigned long integer arguments.
+ * %zu :: Switch to size_t arguments.
+ * %d :: Switch to signed integer arguments.
+ * %ld :: Switch to signed long integer arguments.
+ * ? :: The previous parameter is optional.
*
* In general parameter names are single letters. To use a string for
* a parameter name, enclose the name in single quotes.
@@ -2293,13 +2299,22 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
{
gpg_err_code_t rc;
const char *s, *s2;
- gcry_mpi_t *array[20];
+ void **array[20];
char arrayisdesc[20];
int idx;
gcry_sexp_t l1 = NULL;
int mode = '+'; /* Default to GCRYMPI_FMT_USG. */
+ int submode = 0;
gcry_sexp_t freethis = NULL;
-
+ char *tmpstr = NULL;
+
+ /* Values in ARRAYISDESC describing what the ARRAY holds.
+ * 0 - MPI
+ * 1 - gcry_buffer_t provided by caller.
+ * 2 - gcry_buffer_t allocated by us.
+ * 's' - String allocated by us.
+ * 'x' - Ignore
+ */
memset (arrayisdesc, 0, sizeof arrayisdesc);
/* First copy all the args into an array. This is required so that
@@ -2309,6 +2324,15 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
{
if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
;
+ else if (*s == '%')
+ {
+ s++;
+ if (*s == 'l' && (s[1] == 'u' || s[1] == 'd'))
+ s++;
+ else if (*s == 'z' && s[1] == 'u')
+ s++;
+ continue;
+ }
else if (whitespacep (s))
;
else
@@ -2324,7 +2348,7 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
}
s = s2;
}
- array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
+ array[idx] = va_arg (arg_ptr, void *);
if (!array[idx])
return GPG_ERR_MISSING_VALUE; /* NULL pointer given. */
idx++;
@@ -2368,6 +2392,30 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
{
if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
mode = *s;
+ else if (*s == '%')
+ {
+ s++;
+ if (!*s)
+ continue; /* Ignore at end of format. */
+ if (*s == 's' || *s == 'd' || *s == 'u')
+ {
+ mode = *s;
+ submode = 0;
+ }
+ else if (*s == 'l' && (s[1] == 'u' || s[1] == 'd'))
+ {
+ mode = s[1];
+ submode = 'l';
+ s++;
+ }
+ else if (*s == 'z' && s[1] == 'u')
+ {
+ mode = s[1];
+ submode = 'z';
+ s++;
+ }
+ continue;
+ }
else if (whitespacep (s))
;
else if (*s == '?')
@@ -2404,6 +2452,29 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
}
spec->len = 0;
}
+ else if (mode == 's')
+ {
+ *array[idx] = NULL;
+ arrayisdesc[idx] = 's';
+ }
+ else if (mode == 'd')
+ {
+ if (submode == 'l')
+ *(long *)array[idx] = 0;
+ else
+ *(int *)array[idx] = 0;
+ arrayisdesc[idx] = 'x';
+ }
+ else if (mode == 'u')
+ {
+ if (submode == 'l')
+ *(unsigned long *)array[idx] = 0;
+ else if (submode == 'z')
+ *(size_t *)array[idx] = 0;
+ else
+ *(unsigned int *)array[idx] = 0;
+ arrayisdesc[idx] = 'x';
+ }
else
*array[idx] = NULL;
}
@@ -2451,27 +2522,79 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
arrayisdesc[idx] = 2;
}
}
- else if (mode == '/')
- *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
- else if (mode == '-')
- *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
+ else if (mode == 's')
+ {
+ *array[idx] = _gcry_sexp_nth_string (l1, 1);
+ if (!*array[idx])
+ {
+ rc = gpg_err_code_from_syserror ();
+ goto cleanup;
+ }
+ arrayisdesc[idx] = 's';
+ }
+ else if (mode == 'd')
+ {
+ long along;
+
+ xfree (tmpstr);
+ tmpstr = _gcry_sexp_nth_string (l1, 1);
+ if (!tmpstr)
+ {
+ rc = gpg_err_code_from_syserror ();
+ goto cleanup;
+ }
+ along = strtol (tmpstr, NULL, 10);
+ if (submode == 'l')
+ *(long *)array[idx] = along;
+ else
+ *(int *)array[idx] = along;
+ arrayisdesc[idx] = 'x';
+ }
+ else if (mode == 'u')
+ {
+ long aulong;
+
+ xfree (tmpstr);
+ tmpstr = _gcry_sexp_nth_string (l1, 1);
+ if (!tmpstr)
+ {
+ rc = gpg_err_code_from_syserror ();
+ goto cleanup;
+ }
+ aulong = strtoul (tmpstr, NULL, 10);
+ if (submode == 'l')
+ *(unsigned long *)array[idx] = aulong;
+ else if (submode == 'z')
+ *(size_t *)array[idx] = aulong;
+ else
+ *(unsigned int *)array[idx] = aulong;
+ arrayisdesc[idx] = 'x';
+ }
else
- *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
- sexp_release (l1); l1 = NULL;
- if (!*array[idx])
{
- rc = GPG_ERR_INV_OBJ; /* Conversion failed. */
- goto cleanup;
+ if (mode == '/')
+ *array[idx] = _gcry_sexp_nth_mpi (l1,1,GCRYMPI_FMT_OPAQUE); else if (mode == '-')
+ *array[idx] = _gcry_sexp_nth_mpi (l1,1,GCRYMPI_FMT_STD);
+ else
+ *array[idx] = _gcry_sexp_nth_mpi (l1,1,GCRYMPI_FMT_USG);
+ if (!*array[idx])
+ {
+ rc = GPG_ERR_INV_OBJ; /* Conversion failed. */
+ goto cleanup;
+ }
}
+ sexp_release (l1); l1 = NULL;
}
idx++;
}
}
+ xfree (tmpstr);
sexp_release (freethis);
return 0;
cleanup:
+ xfree (tmpstr);
sexp_release (freethis);
sexp_release (l1);
while (idx--)
@@ -2487,7 +2610,7 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
spec->len = 0;
}
- else
+ else if (arrayisdesc[idx] == 2)
{
/* We might have allocated a buffer. */
gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
@@ -2495,6 +2618,12 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
spec->data = NULL;
spec->size = spec->off = spec->len = 0;
}
+ else if (arrayisdesc[idx] == 's')
+ {
+ /* We might have allocated a buffer. */
+ xfree (*array[idx]);
+ *array[idx] = NULL;
+ }
}
return rc;
}
diff --git a/tests/t-sexp.c b/tests/t-sexp.c
index 93a8d43d..94a97e17 100644
--- a/tests/t-sexp.c
+++ b/tests/t-sexp.c
@@ -608,7 +608,7 @@ static void
check_extract_param (void)
{
/* This sample data is a real key but with some parameters of the
- public key modified. */
+ public key modified. u,i,I are used for direct extraction tests. */
static char sample1[] =
"(key-data"
" (public-key"
@@ -624,6 +624,10 @@ check_extract_param (void)
" (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
"))"
" (private-key"
+ " (u +65537)"
+ " (i +65537)"
+ " (I -65535)"
+ " (i0 1:0)"
" (ecc"
" (curve Ed25519)"
" (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
@@ -820,6 +824,12 @@ check_extract_param (void)
gcry_mpi_t mpis[7];
gcry_buffer_t ioarray[7];
char iobuffer[200];
+ char *string1, *string2;
+ int aint0, aint1, aint2;
+ unsigned int auint;
+ long along1, along2;
+ unsigned long aulong;
+ size_t asize;
info ("checking gcry_sexp_extract_param\n");
for (idx=0; tests[idx].sexp_str; idx++)
@@ -1070,8 +1080,70 @@ check_extract_param (void)
gcry_sexp_release (sxp1);
}
+ info ("checking gcry_sexp_extract_param new modes\n");
+
+ memset (mpis, 0, sizeof mpis);
+
gcry_sexp_release (sxp);
+ err = gcry_sexp_new (&sxp, sample1, 0, 1);
+ if (err)
+ die ("converting string to sexp failed: %s", gpg_strerror (err));
+
+ err = gcry_sexp_extract_param (sxp, "key-data!private-key",
+ "%s'curve'+p%s'comment'"
+ "%uu%di%dI%d'i0'"
+ "%luu%ldi %ldI"
+ "%zui",
+ &string1, mpis+0, &string2,
+ &auint, &aint1, &aint2, &aint0,
+ &aulong, &along1, &along2,
+ &asize,
+ NULL);
+ if (err)
+ fail ("gcry_sexp_extract_param new modes failed: %s", gpg_strerror (err));
+
+ if (!string1)
+ fail ("gcry_sexp_extract_param new modes: no curve");
+ else if (strcmp (string1, "Ed25519"))
+ {
+ fail ("gcry_sexp_extract_param new modes failed: curve mismatch");
+ gcry_log_debug ("expected: %s\n", "Ed25519");
+ gcry_log_debug (" got: %s\n", string1);
+ }
+ if (!mpis[0])
+ fail ("gcry_sexp_extract_param new modes failed: p not returned");
+ else if (cmp_mpihex (mpis[0], sample1_p))
+ {
+ fail ("gcry_sexp_extract_param new modes failed: p mismatch");
+ gcry_log_debug ("expected: %s\n", sample1_p);
+ gcry_log_debugmpi (" got", mpis[0]);
+ }
+
+ if (auint != 65537)
+ fail ("gcry_sexp_extract_param new modes failed: auint mismatch");
+ if (aint1 != 65537)
+ fail ("gcry_sexp_extract_param new modes failed: aint1 mismatch");
+ if (aint2 != -65535)
+ fail ("gcry_sexp_extract_param new modes failed: aint2 mismatch");
+ if (aint0)
+ fail ("gcry_sexp_extract_param new modes failed: aint0 mismatch");
+ if (aulong != 65537)
+ fail ("gcry_sexp_extract_param new modes failed: aulong mismatch");
+ if (along1 != 65537)
+ fail ("gcry_sexp_extract_param new modes failed: along1 mismatch");
+ if (along2 != -65535)
+ fail ("gcry_sexp_extract_param new modes failed: along2 mismatch");
+ if (asize != 65537)
+ fail ("gcry_sexp_extract_param new modes failed: asize mismatch");
+
+
+ gcry_free (string1);
+ gcry_free (string2);
+ gcry_mpi_release (mpis[0]);
+
+
+ gcry_sexp_release (sxp);
}
@@ -1151,6 +1223,7 @@ int
main (int argc, char **argv)
{
int last_argc = -1;
+ int loop = 0;
if (argc)
{
@@ -1185,6 +1258,15 @@ main (int argc, char **argv)
verbose = debug = 1;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--loop"))
+ {
+ argc--; argv++;
+ if (argc)
+ {
+ loop = atoi (*argv);
+ argc--; argv++;
+ }
+ }
else if (!strncmp (*argv, "--", 2))
die ("unknown option '%s'", *argv);
}
@@ -1202,12 +1284,16 @@ main (int argc, char **argv)
xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
- basic ();
- canon_len ();
- back_and_forth ();
- check_sscan ();
- check_extract_param ();
- bug_1594 ();
+ do
+ {
+ basic ();
+ canon_len ();
+ back_and_forth ();
+ check_sscan ();
+ check_extract_param ();
+ bug_1594 ();
+ }
+ while (!error_count && loop--);
return error_count? 1:0;
}