diff options
author | Werner Koch <wk@gnupg.org> | 2020-04-09 20:08:19 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2020-04-09 20:09:03 +0200 |
commit | 60c179b59e538aebb3a5f7621d92eee60b90c785 (patch) | |
tree | 287f4fd6fc3ac1321e2490638fc46f1147dadb72 | |
parent | 1250a9cd859d99f487ca8d76a98d70d464324bbe (diff) | |
download | libgcrypt-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-- | NEWS | 8 | ||||
-rw-r--r-- | doc/gcrypt.texi | 21 | ||||
-rw-r--r-- | src/sexp.c | 165 | ||||
-rw-r--r-- | tests/t-sexp.c | 100 |
4 files changed, 268 insertions, 26 deletions
@@ -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. @@ -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; } |