summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--doc/gcrypt.texi25
-rw-r--r--src/g10lib.h5
-rw-r--r--src/gcrypt.h.in1
-rw-r--r--src/global.c217
-rw-r--r--src/libgcrypt.def2
-rw-r--r--src/libgcrypt.vers2
-rw-r--r--src/misc.c12
-rw-r--r--src/visibility.c6
-rw-r--r--src/visibility.h2
-rw-r--r--tests/version.c49
11 files changed, 248 insertions, 74 deletions
diff --git a/NEWS b/NEWS
index d7e9bd9a..c97f4256 100644
--- a/NEWS
+++ b/NEWS
@@ -67,6 +67,7 @@ Noteworthy changes in version 1.8.0 (unreleased) [C21/A1/R_]
* Interface changes relative to the 1.7.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRYCTL_REINIT_SYSCALL_CLAMP NEW macro.
+ gcry_get_config NEW function.
gcry_md_info DEPRECATED.
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 26dd6c3d..cab1318d 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -824,7 +824,8 @@ proper random device.
This command dumps information pertaining to the configuration of the
library to the given stream. If NULL is given for @var{stream}, the log
system is used. This command may be used before the initialization has
-been finished but not before a @code{gcry_check_version}.
+been finished but not before a @code{gcry_check_version}. Note that
+the macro @code{estream_t} can be used instead of @code{gpgrt_stream_t}.
@item GCRYCTL_OPERATIONAL_P; Arguments: none
This command returns true if the library is in an operational state.
@@ -5233,6 +5234,7 @@ wrong.
* Memory allocation:: Functions related with memory allocation.
* Context management:: Functions related with context management.
* Buffer description:: A data type to describe buffers.
+* Config reporting:: How to return Libgcrypt's configuration.
@end menu
@@ -5317,6 +5319,27 @@ of this structure are:
@end table
@end deftp
+@node Config reporting
+@section How to return Libgcrypt's configuration.
+
+Although @code{GCRYCTL_PRINT_CONFIG} can be used to print
+configuration options, it is sometimes necessary to check them in a
+program. This can be accomplished by using this function:
+
+@deftypefun {char *} gcry_get_config @
+ (@w{int @var{mode}}, @
+ @w{const char *@var{what}})
+
+This function returns a malloced string with colon delimited configure
+options. With a value of 0 for @var{mode} this string resembles the
+output of @code{GCRYCTL_PRINT_CONFIG}. However, if @var{what} is not
+NULL, only the line where the first field (e.g. "cpu-arch") matches
+@var{what} is returned.
+
+Other values than 0 for @var{mode} are not defined. The caller shall
+free the string using @code{gcry_free}. On error NULL is returned and
+ERRNO is set; if a value for WHAT is unknow ERRNO will be set to 0.
+@end deftypefun
@c **********************************************************
diff --git a/src/g10lib.h b/src/g10lib.h
index ec8aab56..961b5154 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -109,6 +109,8 @@ void _gcry_pre_syscall (void);
void _gcry_post_syscall (void);
int _gcry_get_debug_flag (unsigned int mask);
+char *_gcry_get_config (int mode, const char *what);
+
/* Malloc functions and common wrapper macros. */
void *_gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
@@ -163,8 +165,6 @@ void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void _gcry_log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
-int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... )
- JNLIB_GCC_A_PRINTF(2,3);
void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_printhex (const char *text, const void *buffer, size_t length);
@@ -174,6 +174,7 @@ void _gcry_log_printsxp (const char *text, gcry_sexp_t sexp);
void _gcry_set_log_verbosity( int level );
int _gcry_log_verbosity( int level );
+
#ifdef JNLIB_GCC_M_FUNCTION
#define BUG() _gcry_bug( __FILE__ , __LINE__, __FUNCTION__ )
#define gcry_assert(expr) (LIKELY(expr)? (void)0 \
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 210ea2fd..8d20c83b 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1691,6 +1691,7 @@ void gcry_log_debugpnt (const char *text,
gcry_mpi_point_t point, gcry_ctx_t ctx);
void gcry_log_debugsxp (const char *text, gcry_sexp_t sexp);
+char *gcry_get_config (int mode, const char *what);
/* Log levels used by the internal logging facility. */
enum gcry_log_levels
diff --git a/src/global.c b/src/global.c
index 0796a945..4e2e274a 100644
--- a/src/global.c
+++ b/src/global.c
@@ -2,7 +2,7 @@
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2004, 2005, 2006, 2008, 2011,
* 2012 Free Software Foundation, Inc.
- * Copyright (C) 2013, 2014 g10 Code GmbH
+ * Copyright (C) 2013, 2014, 2017 g10 Code GmbH
*
* This file is part of Libgcrypt.
*
@@ -273,91 +273,181 @@ _gcry_check_version (const char *req_version)
static void
-print_config ( int (*fnc)(FILE *fp, const char *format, ...), FILE *fp)
+print_config (const char *what, gpgrt_stream_t fp)
{
- unsigned int hwfeatures, afeature;
int i;
const char *s;
- fnc (fp, "version:%s:%x:%s:%x:\n",
- VERSION, GCRYPT_VERSION_NUMBER,
- GPGRT_VERSION, GPGRT_VERSION_NUMBER);
- fnc (fp, "cc:%d:%s:\n",
+ if (!what || !strcmp (what, "version"))
+ {
+ gpgrt_fprintf (fp, "version:%s:%x:%s:%x:\n",
+ VERSION, GCRYPT_VERSION_NUMBER,
+ GPGRT_VERSION, GPGRT_VERSION_NUMBER);
+ }
+ if (!what || !strcmp (what, "cc"))
+ {
+ gpgrt_fprintf (fp, "cc:%d:%s:\n",
#if GPGRT_VERSION_NUMBER >= 0x011b00 /* 1.27 */
- GPGRT_GCC_VERSION
+ GPGRT_GCC_VERSION
#else
- _GPG_ERR_GCC_VERSION /* Due to a bug in gpg-error.h. */
+ _GPG_ERR_GCC_VERSION /* Due to a bug in gpg-error.h. */
#endif
- ,
+ ,
#ifdef __clang__
- "clang:" __VERSION__
+ "clang:" __VERSION__
#elif __GNUC__
- "gcc:" __VERSION__
+ "gcc:" __VERSION__
#else
- ":"
+ ":"
#endif
- );
+ );
+ }
- fnc (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS);
- fnc (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS);
- fnc (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS);
- fnc (fp, "rnd-mod:"
+ if (!what || !strcmp (what, "ciphers"))
+ gpgrt_fprintf (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS);
+ if (!what || !strcmp (what, "pubkeys"))
+ gpgrt_fprintf (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS);
+ if (!what || !strcmp (what, "digests"))
+ gpgrt_fprintf (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS);
+
+ if (!what || !strcmp (what, "rnd-mod"))
+ {
+ gpgrt_fprintf (fp, "rnd-mod:"
#if USE_RNDEGD
- "egd:"
+ "egd:"
#endif
#if USE_RNDLINUX
- "linux:"
+ "linux:"
#endif
#if USE_RNDUNIX
- "unix:"
+ "unix:"
#endif
#if USE_RNDW32
- "w32:"
+ "w32:"
#endif
- "\n");
- fnc (fp, "cpu-arch:"
+ "\n");
+ }
+
+ if (!what || !strcmp (what, "cpu-arch"))
+ {
+ gpgrt_fprintf (fp, "cpu-arch:"
#if defined(HAVE_CPU_ARCH_X86)
- "x86"
+ "x86"
#elif defined(HAVE_CPU_ARCH_ALPHA)
- "alpha"
+ "alpha"
#elif defined(HAVE_CPU_ARCH_SPARC)
- "sparc"
+ "sparc"
#elif defined(HAVE_CPU_ARCH_MIPS)
- "mips"
+ "mips"
#elif defined(HAVE_CPU_ARCH_M68K)
- "m68k"
+ "m68k"
#elif defined(HAVE_CPU_ARCH_PPC)
- "ppc"
+ "ppc"
#elif defined(HAVE_CPU_ARCH_ARM)
- "arm"
+ "arm"
#endif
- ":\n");
- fnc (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ());
- hwfeatures = _gcry_get_hw_features ();
- fnc (fp, "hwflist:");
- for (i=0; (s = _gcry_enum_hw_features (i, &afeature)); i++)
- if ((hwfeatures & afeature))
- fnc (fp, "%s:", s);
- fnc (fp, "\n");
- /* We use y/n instead of 1/0 for the simple reason that Emacsen's
- compile error parser would accidentally flag that line when printed
- during "make check" as an error. */
- fnc (fp, "fips-mode:%c:%c:\n",
- fips_mode ()? 'y':'n',
- _gcry_enforced_fips_mode ()? 'y':'n' );
- /* The currently used RNG type. */
- {
- i = _gcry_get_rng_type (0);
- switch (i)
- {
- case GCRY_RNG_TYPE_STANDARD: s = "standard"; break;
- case GCRY_RNG_TYPE_FIPS: s = "fips"; break;
- case GCRY_RNG_TYPE_SYSTEM: s = "system"; break;
- default: BUG ();
- }
- fnc (fp, "rng-type:%s:%d:\n", s, i);
- }
+ ":\n");
+ }
+
+ if (!what || !strcmp (what, "mpi-asm"))
+ gpgrt_fprintf (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ());
+
+ if (!what || !strcmp (what, "hwflist"))
+ {
+ unsigned int hwfeatures, afeature;
+
+ hwfeatures = _gcry_get_hw_features ();
+ gpgrt_fprintf (fp, "hwflist:");
+ for (i=0; (s = _gcry_enum_hw_features (i, &afeature)); i++)
+ if ((hwfeatures & afeature))
+ gpgrt_fprintf (fp, "%s:", s);
+ gpgrt_fprintf (fp, "\n");
+ }
+
+ if (!what || !strcmp (what, "fips-mode"))
+ {
+ /* We use y/n instead of 1/0 for the stupid reason that
+ * Emacsen's compile error parser would accidentally flag that
+ * line when printed during "make check" as an error. */
+ gpgrt_fprintf (fp, "fips-mode:%c:%c:\n",
+ fips_mode ()? 'y':'n',
+ _gcry_enforced_fips_mode ()? 'y':'n' );
+ }
+
+ if (!what || !strcmp (what, "rng-type"))
+ {
+ /* The currently used RNG type. */
+ unsigned int jver;
+ int active;
+
+ i = _gcry_get_rng_type (0);
+ switch (i)
+ {
+ case GCRY_RNG_TYPE_STANDARD: s = "standard"; break;
+ case GCRY_RNG_TYPE_FIPS: s = "fips"; break;
+ case GCRY_RNG_TYPE_SYSTEM: s = "system"; break;
+ default: BUG ();
+ }
+ jver = _gcry_rndjent_get_version (&active);
+ gpgrt_fprintf (fp, "rng-type:%s:%d:%u:%d:\n", s, i, jver, active);
+ }
+}
+
+
+/* With a MODE of 0 return a malloced string with configured features.
+ * In that case a WHAT of NULL returns everything in the same way
+ * GCRYCTL_PRINT_CONFIG would do. With a specific WHAT string only
+ * the requested feature is returned (w/o the trailing LF. On error
+ * NULL is returned. */
+char *
+_gcry_get_config (int mode, const char *what)
+{
+ gpgrt_stream_t fp;
+ int save_errno;
+ void *data;
+ char *p;
+
+ if (mode)
+ {
+ gpg_err_set_errno (EINVAL);
+ return NULL;
+ }
+
+ fp = gpgrt_fopenmem (0, "w+b,samethread");
+ if (!fp)
+ return NULL;
+
+ print_config (what, fp);
+ if (gpgrt_ferror (fp))
+ {
+ save_errno = errno;
+ gpgrt_fclose (fp);
+ gpg_err_set_errno (save_errno);
+ return NULL;
+ }
+
+ gpgrt_rewind (fp);
+ if (gpgrt_fclose_snatch (fp, &data, NULL))
+ {
+ save_errno = errno;
+ gpgrt_fclose (fp);
+ gpg_err_set_errno (save_errno);
+ return NULL;
+ }
+
+ if (!data)
+ {
+ /* Nothing was printed (unknown value for WHAT). This is okay,
+ * so clear ERRNO to indicate this. */
+ gpg_err_set_errno (0);
+ return NULL;
+ }
+
+ /* Strip trailing LF. */
+ if (what && (p = strchr (data, '\n')))
+ *p = 0;
+ return data;
}
@@ -549,12 +639,21 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
/* This command dumps information pertaining to the
configuration of libgcrypt to the given stream. It may be
used before the initialization has been finished but not
- before a gcry_version_check. */
+ before a gcry_version_check. See also gcry_get_config. */
case GCRYCTL_PRINT_CONFIG:
{
FILE *fp = va_arg (arg_ptr, FILE *);
+ char *tmpstr;
_gcry_set_preferred_rng_type (0);
- print_config (fp?fprintf:_gcry_log_info_with_dummy_fp, fp);
+ tmpstr = _gcry_get_config (0, NULL);
+ if (tmpstr)
+ {
+ if (fp)
+ fputs (tmpstr, fp);
+ else
+ log_info ("%s", tmpstr);
+ xfree (tmpstr);
+ }
}
break;
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 067cb843..c4a9eacc 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -282,4 +282,6 @@ EXPORTS
gcry_mpi_ec_decode_point @246
+ gcry_get_config @247
+
;; end of file with public symbols for Windows.
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 785b8ed2..1d2d150a 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -111,6 +111,8 @@ GCRYPT_1.6 {
gcry_log_debug;
gcry_log_debughex; gcry_log_debugmpi; gcry_log_debugpnt; gcry_log_debugsxp;
+ gcry_get_config;
+
_gcry_mpi_get_const;
gcry_ctx_release;
diff --git a/src/misc.c b/src/misc.c
index 9d8b7bd8..002a84f6 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -198,18 +198,6 @@ _gcry_log_info( const char *fmt, ... )
va_end(arg_ptr);
}
-int
-_gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... )
-{
- va_list arg_ptr;
-
- (void)fp;
- va_start( arg_ptr, fmt ) ;
- _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
- va_end(arg_ptr);
- return 0;
-}
-
void
_gcry_log_error( const char *fmt, ... )
{
diff --git a/src/visibility.c b/src/visibility.c
index 3abbd379..7bf3d57b 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1435,6 +1435,12 @@ gcry_log_debugsxp (const char *text, gcry_sexp_t sexp)
_gcry_log_printsxp (text, sexp);
}
+char *
+gcry_get_config (int mode, const char *what)
+{
+ return _gcry_get_config (mode, what);
+}
+
void
gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data)
{
diff --git a/src/visibility.h b/src/visibility.h
index 7ecd75e3..d28993a8 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -279,6 +279,8 @@ MARK_VISIBLEX (gcry_log_debugmpi)
MARK_VISIBLEX (gcry_log_debugpnt)
MARK_VISIBLEX (gcry_log_debugsxp)
+MARK_VISIBLEX (gcry_get_config)
+
/* Functions used to implement macros. */
MARK_VISIBLEX (_gcry_mpi_get_const)
diff --git a/tests/version.c b/tests/version.c
index baf984ec..6a01610d 100644
--- a/tests/version.c
+++ b/tests/version.c
@@ -32,12 +32,58 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#include <errno.h>
#include "../src/gcrypt-int.h"
#define PGM "version"
#include "t-common.h"
+static void
+test_get_config (void)
+{
+ char *string;
+
+ string = gcry_get_config (0, NULL);
+ if (!string)
+ fail ("gcry_get_config does not return anything: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ else if ( !strchr (string, '\n') )
+ fail ("gcry_get_config(0, NULL) did not return multiple lines\n");
+
+ xfree (string);
+ string = gcry_get_config (0, "version");
+ if (!string)
+ fail ("gcry_get_config(\"version\") returned NULL: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ else if ( strchr (string, '\n') )
+ fail ("gcry_get_config(\"version\") returned more than one line\n");
+ else if ( strncmp (string, "version:", 8) )
+ fail ("gcry_get_config(\"version\") returned wrong line\n");
+
+ /* Test an item which is not the first. */
+ xfree (string);
+ string = gcry_get_config (0, "cpu-arch");
+ if (!string)
+ fail ("gcry_get_config(\"cpu-arch\") returned NULL: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ else if ( strchr (string, '\n') )
+ fail ("gcry_get_config(\"cpu-arch\") returned more than one line\n");
+ else if ( strncmp (string, "cpu-arch:", 9) )
+ fail ("gcry_get_config(\"cpu-arch\") returned wrong line\n");
+
+ /* Test that an unknown item return sthe correct error. */
+ xfree (string);
+ string = gcry_get_config (0, "no-such-item");
+ if (string)
+ fail ("gcry_get_config(\"no-such-item\") returned something\n");
+ else if (errno)
+ fail ("gcry_get_config(\"no-such-item\") returned wrong error: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+
+ xfree (string);
+}
+
int
main (int argc, char **argv)
@@ -96,5 +142,8 @@ main (int argc, char **argv)
xgcry_control (GCRYCTL_PRINT_CONFIG, NULL);
+ test_get_config ();
+
+
return 0;
}