summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/gcrypt.texi24
-rw-r--r--src/sexp.c47
-rw-r--r--tests/tsexp.c71
3 files changed, 125 insertions, 17 deletions
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 91168a83..927634f1 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4145,10 +4145,10 @@ likely want to use @code{GCRYMPI_FMT_USG}.
@w{const char *@var{path}}, @
@w{const char *@var{list}}, ...)
-Extract parameters from an S-expression using a list of single letter
-parameter names. The names of these parameters are specified in
-LIST. Some special characters may be given to control the
-conversion:
+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:
@table @samp
@item +
@@ -4162,21 +4162,25 @@ computations; see @code{gcry_mpi_get_opaque} for details.
@item &
Switch to buffer descriptor mode. See below for details.
@item ?
-If immediately following a parameter letter, that parameter is
-considered optional.
+If immediately following a parameter letter (no white space allowed),
+that parameter is considered optional.
@end table
+In general parameter names are single letters. To use a string for a
+parameter name, enclose the name in single quotes.
+
Unless in buffer descriptor mode for each parameter name a pointer to
an @code{gcry_mpi_t} variable is expected finally followed by a @code{NULL}.
For example
@example
- _gcry_sexp_extract_param (key, NULL, "n/x+ed",
- &mpi_n, &mpi_x, &mpi_e, NULL)
+ _gcry_sexp_extract_param (key, NULL, "n/x+e d-'foo'",
+ &mpi_n, &mpi_x, &mpi_e, &mpi_foo, NULL)
@end example
stores the parameter 'n' from @var{key} as an unsigned MPI into
-@var{mpi_n}, the parameter 'x' as an opaque MPI into @var{mpi_x}, and
-the parameter 'e' again as an unsigned MPI into @var{mpi_e}.
+@var{mpi_n}, the parameter 'x' as an opaque MPI into @var{mpi_x}, the
+parameter 'e' again as an unsigned MPI into @var{mpi_e}, and the
+parameter 'foo' as a signed MPI.
@var{path} is an optional string used to locate a token. The
exclamation mark separated tokens are used via
diff --git a/src/sexp.c b/src/sexp.c
index 16def5b4..7ff4c0a5 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -2113,10 +2113,9 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
}
-/* Extract MPIs from an s-expression using a list of one letter
- * parameters. The names of these parameters are given by the string
- * LIST. Some special characters may be given to control the
- * conversion:
+/* Extract MPIs from an s-expression using a list of parameters. The
+ * 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.
@@ -2124,6 +2123,9 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
* & :: Switch to buffer descriptor mode - see below.
* ? :: 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.
+ *
* Unless in gcry_buffer_t mode for each parameter name a pointer to
* an MPI variable is expected and finally a NULL is expected.
* Example:
@@ -2158,7 +2160,7 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
const char *list, va_list arg_ptr)
{
gpg_err_code_t rc;
- const char *s;
+ const char *s, *s2;
gcry_mpi_t *array[20];
char arrayisdesc[20];
int idx;
@@ -2173,10 +2175,23 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
was found. */
for (s=list, idx=0; *s && idx < DIM (array); s++)
{
- if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?' )
+ if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
+ ;
+ else if (whitespacep (s))
;
else
{
+ if (*s == '\'')
+ {
+ s++;
+ s2 = strchr (s, '\'');
+ if (!s2 || s2 == s)
+ {
+ /* Closing quote not found or empty string. */
+ return GPG_ERR_SYNTAX;
+ }
+ s = s2;
+ }
array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
if (!array[idx])
return GPG_ERR_MISSING_VALUE; /* NULL pointer given. */
@@ -2221,11 +2236,29 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
{
if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
mode = *s;
+ else if (whitespacep (s))
+ ;
else if (*s == '?')
; /* Only used via lookahead. */
else
{
- l1 = _gcry_sexp_find_token (sexp, s, 1);
+ if (*s == '\'')
+ {
+ /* Find closing quote, find token, set S to closing quote. */
+ s++;
+ s2 = strchr (s, '\'');
+ if (!s2 || s2 == s)
+ {
+ /* Closing quote not found or empty string. */
+ rc = GPG_ERR_SYNTAX;
+ goto cleanup;
+ }
+ l1 = _gcry_sexp_find_token (sexp, s, s2 - s);
+ s = s2;
+ }
+ else
+ l1 = _gcry_sexp_find_token (sexp, s, 1);
+
if (!l1 && s[1] == '?')
{
/* Optional element not found. */
diff --git a/tests/tsexp.c b/tests/tsexp.c
index afa79ff7..2f6ad8f9 100644
--- a/tests/tsexp.c
+++ b/tests/tsexp.c
@@ -684,6 +684,18 @@ check_extract_param (void)
{
sample1,
NULL,
+ "pab'gnq", 7,
+ GPG_ERR_SYNTAX
+ },
+ {
+ sample1,
+ NULL,
+ "pab''gnq", 7,
+ GPG_ERR_SYNTAX
+ },
+ {
+ sample1,
+ NULL,
"pabgnqd", 7,
0,
sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
@@ -692,6 +704,14 @@ check_extract_param (void)
{
sample1,
NULL,
+ " pab\tg nq\nd ", 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
@@ -699,6 +719,13 @@ check_extract_param (void)
{
sample1,
NULL,
+ "ab'g'", 3,
+ 0,
+ sample1_ax, sample1_bx, sample1_gx
+ },
+ {
+ sample1,
+ NULL,
"x?abg", 4,
0,
NULL, sample1_ax, sample1_bx, sample1_gx
@@ -967,6 +994,50 @@ check_extract_param (void)
}
gcry_sexp_release (sxp);
+
+ info ("checking gcry_sexp_extract_param long name\n");
+
+ memset (ioarray, 0, sizeof ioarray);
+ memset (mpis, 0, sizeof mpis);
+
+ 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",
+ "&'curve'+p",
+ ioarray+0, mpis+0, NULL);
+ if (err)
+ fail ("gcry_sexp_extract_param long name failed: %s", gpg_strerror (err));
+
+ if (!ioarray[0].data)
+ fail ("gcry_sexp_extract_param long name failed: no curve");
+ else if (ioarray[0].size != 7)
+ fail ("gcry_sexp_extract_param long name failed: curve has wrong size");
+ else if (ioarray[0].len != 7)
+ fail ("gcry_sexp_extract_param long name failed: curve has wrong length");
+ else if (ioarray[0].off)
+ fail ("gcry_sexp_extract_param long name failed: curve has OFF set");
+ else if (strncmp (ioarray[0].data, "Ed25519", 7))
+ {
+ fail ("gcry_sexp_extract_param long name failed: curve mismatch");
+ gcry_log_debug ("expected: %s\n", "Ed25519");
+ gcry_log_debug (" got: %.*s\n", (int)ioarray[0].len, ioarray[0].data);
+ }
+
+ if (!mpis[0])
+ fail ("gcry_sexp_extract_param long name failed: p not returned");
+ else if (cmp_mpihex (mpis[0], sample1_p))
+ {
+ fail ("gcry_sexp_extract_param long name failed: p mismatch");
+ gcry_log_debug ("expected: %s\n", sample1_p);
+ gcry_log_debugmpi (" got", mpis[0]);
+ }
+
+ gcry_mpi_release (mpis[0]);
+
+ gcry_sexp_release (sxp);
+
}