diff options
-rw-r--r-- | doc/gcrypt.texi | 24 | ||||
-rw-r--r-- | src/sexp.c | 47 | ||||
-rw-r--r-- | tests/tsexp.c | 71 |
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 @@ -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); + } |