diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 213f3f9f7..e0b723839 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -1,3841 +1,3844 @@
 /* command-ssh.c - gpg-agent's implementation of the ssh-agent protocol.
  * Copyright (C) 2004-2006, 2009, 2012 Free Software Foundation, Inc.
  * Copyright (C) 2004-2006, 2009, 2012-2014 Werner Koch
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 /* Only v2 of the ssh-agent protocol is implemented.  Relevant RFCs
    are:
 
    RFC-4250 - Protocol Assigned Numbers
    RFC-4251 - Protocol Architecture
    RFC-4252 - Authentication Protocol
    RFC-4253 - Transport Layer Protocol
    RFC-5656 - ECC support
 
    The protocol for the agent is defined in OpenSSH's PROTOCL.agent
    file.
   */
 
 #include <config.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <assert.h>
 #ifndef HAVE_W32_SYSTEM
 #include <sys/socket.h>
 #include <sys/un.h>
 #endif /*!HAVE_W32_SYSTEM*/
 #ifdef HAVE_SYS_UCRED_H
 #include <sys/ucred.h>
 #endif
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
 
 #include "agent.h"
 
 #include "../common/i18n.h"
 #include "../common/util.h"
 #include "../common/ssh-utils.h"
 
 
 
 
 /* Request types. */
 #define SSH_REQUEST_REQUEST_IDENTITIES    11
 #define SSH_REQUEST_SIGN_REQUEST          13
 #define SSH_REQUEST_ADD_IDENTITY          17
 #define SSH_REQUEST_REMOVE_IDENTITY       18
 #define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19
 #define SSH_REQUEST_LOCK                  22
 #define SSH_REQUEST_UNLOCK                23
 #define SSH_REQUEST_ADD_ID_CONSTRAINED    25
 
 /* Options. */
 #define	SSH_OPT_CONSTRAIN_LIFETIME	   1
 #define	SSH_OPT_CONSTRAIN_CONFIRM	   2
 
 /* Response types. */
 #define SSH_RESPONSE_SUCCESS               6
 #define SSH_RESPONSE_FAILURE               5
 #define SSH_RESPONSE_IDENTITIES_ANSWER    12
 #define SSH_RESPONSE_SIGN_RESPONSE        14
 
 /* Other constants.  */
 #define SSH_DSA_SIGNATURE_PADDING 20
 #define SSH_DSA_SIGNATURE_ELEMS    2
 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
 #define SPEC_FLAG_IS_ECDSA    (1 << 1)
 #define SPEC_FLAG_IS_EdDSA    (1 << 2)  /*(lowercase 'd' on purpose.)*/
 #define SPEC_FLAG_WITH_CERT   (1 << 7)
 
 /* The name of the control file.  */
 #define SSH_CONTROL_FILE_NAME "sshcontrol"
 
 /* The blurb we put into the header of a newly created control file.  */
 static const char sshcontrolblurb[] =
 "# List of allowed ssh keys.  Only keys present in this file are used\n"
 "# in the SSH protocol.  The ssh-add tool may add new entries to this\n"
 "# file to enable them; you may also add them manually.  Comment\n"
 "# lines, like this one, as well as empty lines are ignored.  Lines do\n"
 "# have a certain length limit but this is not serious limitation as\n"
 "# the format of the entries is fixed and checked by gpg-agent. A\n"
 "# non-comment line starts with optional white spaces, followed by the\n"
 "# keygrip of the key given as 40 hex digits, optionally followed by a\n"
 "# caching TTL in seconds, and another optional field for arbitrary\n"
 "# flags.   Prepend the keygrip with an '!' mark to disable it.\n"
 "\n";
 
 
 /* Macros.  */
 
 /* Return a new uint32 with b0 being the most significant byte and b3
    being the least significant byte.  */
 #define uint32_construct(b0, b1, b2, b3) \
   ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
 
 
 
 
 /*
  * Basic types.
  */
 
 /* Type for a request handler.  */
 typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
 					      estream_t request,
 					      estream_t response);
 
 
 struct ssh_key_type_spec;
 typedef struct ssh_key_type_spec ssh_key_type_spec_t;
 
 /* Type, which is used for associating request handlers with the
    appropriate request IDs.  */
 typedef struct ssh_request_spec
 {
   unsigned char type;
   ssh_request_handler_t handler;
   const char *identifier;
   unsigned int secret_input;
 } ssh_request_spec_t;
 
 /* Type for "key modifier functions", which are necessary since
    OpenSSH and GnuPG treat key material slightly different.  A key
    modifier is called right after a new key identity has been received
    in order to "sanitize" the material.  */
 typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems,
                                            gcry_mpi_t *mpis);
 
 /* The encoding of a generated signature is dependent on the
    algorithm; therefore algorithm specific signature encoding
    functions are necessary.  */
 typedef gpg_error_t (*ssh_signature_encoder_t) (ssh_key_type_spec_t *spec,
                                                 estream_t signature_blob,
 						gcry_sexp_t sig);
 
 /* Type, which is used for boundling all the algorithm specific
    information together in a single object.  */
 struct ssh_key_type_spec
 {
   /* Algorithm identifier as used by OpenSSH.  */
   const char *ssh_identifier;
 
   /* Human readable name of the algorithm.  */
   const char *name;
 
   /* Algorithm identifier as used by GnuPG.  */
   int algo;
 
   /* List of MPI names for secret keys; order matches the one of the
      agent protocol.  */
   const char *elems_key_secret;
 
   /* List of MPI names for public keys; order matches the one of the
      agent protocol.  */
   const char *elems_key_public;
 
   /* List of MPI names for signature data.  */
   const char *elems_signature;
 
   /* List of MPI names for secret keys; order matches the one, which
      is required by gpg-agent's key access layer.  */
   const char *elems_sexp_order;
 
   /* Key modifier function.  Key modifier functions are necessary in
      order to fix any inconsistencies between the representation of
      keys on the SSH and on the GnuPG side.  */
   ssh_key_modifier_t key_modifier;
 
   /* Signature encoder function.  Signature encoder functions are
      necessary since the encoding of signatures depends on the used
      algorithm.  */
   ssh_signature_encoder_t signature_encoder;
 
   /* The name of the ECC curve or NULL.  */
   const char *curve_name;
 
   /* The hash algorithm to be used with this key.  0 for using the
      default.  */
   int hash_algo;
 
   /* Misc flags.  */
   unsigned int flags;
 };
 
 
 /* Definition of an object to access the sshcontrol file.  */
 struct ssh_control_file_s
 {
   char *fname;  /* Name of the file.  */
   FILE *fp;     /* This is never NULL. */
   int lnr;      /* The current line number.  */
   struct {
     int valid;           /* True if the data of this structure is valid.  */
     int disabled;        /* The item is disabled.  */
     int ttl;             /* The TTL of the item.   */
     int confirm;         /* The confirm flag is set.  */
     char hexgrip[40+1];  /* The hexgrip of the item (uppercase).  */
   } item;
 };
 
 
 /* Prototypes.  */
 static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
 						   estream_t request,
 						   estream_t response);
 static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
 					     estream_t request,
 					     estream_t response);
 static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
 					     estream_t request,
 					     estream_t response);
 static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
 						estream_t request,
 						estream_t response);
 static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
 						      estream_t request,
 						      estream_t response);
 static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
 				     estream_t request,
 				     estream_t response);
 static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
 				       estream_t request,
 				       estream_t response);
 
 static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis);
 static gpg_error_t ssh_signature_encoder_rsa (ssh_key_type_spec_t *spec,
                                               estream_t signature_blob,
                                               gcry_sexp_t signature);
 static gpg_error_t ssh_signature_encoder_dsa (ssh_key_type_spec_t *spec,
                                               estream_t signature_blob,
                                               gcry_sexp_t signature);
 static gpg_error_t ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
                                                 estream_t signature_blob,
                                                 gcry_sexp_t signature);
 static gpg_error_t ssh_signature_encoder_eddsa (ssh_key_type_spec_t *spec,
                                                 estream_t signature_blob,
                                                 gcry_sexp_t signature);
 static gpg_error_t ssh_key_extract_comment (gcry_sexp_t key, char **comment);
 
 
 
 /* Global variables.  */
 
 
 /* Associating request types with the corresponding request
    handlers.  */
 
 static const ssh_request_spec_t request_specs[] =
   {
 #define REQUEST_SPEC_DEFINE(id, name, secret_input) \
   { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input }
 
     REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES,    request_identities,    1),
     REQUEST_SPEC_DEFINE (SIGN_REQUEST,          sign_request,          0),
     REQUEST_SPEC_DEFINE (ADD_IDENTITY,          add_identity,          1),
     REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED,    add_identity,          1),
     REQUEST_SPEC_DEFINE (REMOVE_IDENTITY,       remove_identity,       0),
     REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities, 0),
     REQUEST_SPEC_DEFINE (LOCK,                  lock,                  0),
     REQUEST_SPEC_DEFINE (UNLOCK,                unlock,                0)
 #undef REQUEST_SPEC_DEFINE
   };
 
 
 /* Table holding key type specifications.  */
 static const ssh_key_type_spec_t ssh_key_types[] =
   {
     {
       "ssh-ed25519", "Ed25519", GCRY_PK_EDDSA, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_eddsa,
       "Ed25519", 0,               SPEC_FLAG_IS_EdDSA
     },
     {
       "ssh-rsa", "RSA", GCRY_PK_RSA, "nedupq", "en",   "s",  "nedpqu",
       ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
       NULL, 0,                    SPEC_FLAG_USE_PKCS1V2
     },
     {
       "ssh-dss", "DSA", GCRY_PK_DSA, "pqgyx",  "pqgy", "rs", "pqgyx",
       NULL,                 ssh_signature_encoder_dsa,
       NULL, 0, 0
     },
     {
       "ecdsa-sha2-nistp256", "ECDSA", GCRY_PK_ECC, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_ecdsa,
       "nistp256", GCRY_MD_SHA256, SPEC_FLAG_IS_ECDSA
     },
     {
       "ecdsa-sha2-nistp384", "ECDSA", GCRY_PK_ECC, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_ecdsa,
       "nistp384", GCRY_MD_SHA384, SPEC_FLAG_IS_ECDSA
     },
     {
       "ecdsa-sha2-nistp521", "ECDSA", GCRY_PK_ECC, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_ecdsa,
       "nistp521", GCRY_MD_SHA512, SPEC_FLAG_IS_ECDSA
     },
     {
       "ssh-ed25519-cert-v01@openssh.com", "Ed25519",
       GCRY_PK_EDDSA, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_eddsa,
       "Ed25519", 0, SPEC_FLAG_IS_EdDSA | SPEC_FLAG_WITH_CERT
     },
     {
       "ssh-rsa-cert-v01@openssh.com", "RSA",
       GCRY_PK_RSA, "nedupq", "en",   "s",  "nedpqu",
       ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
       NULL, 0, SPEC_FLAG_USE_PKCS1V2 | SPEC_FLAG_WITH_CERT
     },
     {
       "ssh-dss-cert-v01@openssh.com", "DSA",
       GCRY_PK_DSA, "pqgyx",  "pqgy", "rs", "pqgyx",
       NULL,                 ssh_signature_encoder_dsa,
       NULL, 0, SPEC_FLAG_WITH_CERT | SPEC_FLAG_WITH_CERT
     },
     {
       "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA",
       GCRY_PK_ECC, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_ecdsa,
       "nistp256", GCRY_MD_SHA256, SPEC_FLAG_IS_ECDSA | SPEC_FLAG_WITH_CERT
     },
     {
       "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA",
       GCRY_PK_ECC, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_ecdsa,
       "nistp384", GCRY_MD_SHA384, SPEC_FLAG_IS_ECDSA | SPEC_FLAG_WITH_CERT
     },
     {
       "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA",
       GCRY_PK_ECC, "qd",  "q", "rs", "qd",
       NULL,                 ssh_signature_encoder_ecdsa,
       "nistp521", GCRY_MD_SHA512, SPEC_FLAG_IS_ECDSA | SPEC_FLAG_WITH_CERT
     }
   };
 
 
 
 
 
 /*
    General utility functions.
  */
 
 /* A secure realloc, i.e. it makes sure to allocate secure memory if A
    is NULL.  This is required because the standard gcry_realloc does
    not know whether to allocate secure or normal if NULL is passed as
    existing buffer.  */
 static void *
 realloc_secure (void *a, size_t n)
 {
   void *p;
 
   if (a)
     p = gcry_realloc (a, n);
   else
     p = gcry_malloc_secure (n);
 
   return p;
 }
 
 
 /* Lookup the ssh-identifier for the ECC curve CURVE_NAME.  Returns
    NULL if not found.  */
 static const char *
 ssh_identifier_from_curve_name (const char *curve_name)
 {
   int i;
 
   for (i = 0; i < DIM (ssh_key_types); i++)
     if (ssh_key_types[i].curve_name
         && !strcmp (ssh_key_types[i].curve_name, curve_name))
       return ssh_key_types[i].ssh_identifier;
 
   return NULL;
 }
 
 
 /*
    Primitive I/O functions.
  */
 
 
 /* Read a byte from STREAM, store it in B.  */
 static gpg_error_t
 stream_read_byte (estream_t stream, unsigned char *b)
 {
   gpg_error_t err;
   int ret;
 
   ret = es_fgetc (stream);
   if (ret == EOF)
     {
       if (es_ferror (stream))
 	err = gpg_error_from_syserror ();
       else
 	err = gpg_error (GPG_ERR_EOF);
       *b = 0;
     }
   else
     {
       *b = ret & 0xFF;
       err = 0;
     }
 
   return err;
 }
 
 /* Write the byte contained in B to STREAM.  */
 static gpg_error_t
 stream_write_byte (estream_t stream, unsigned char b)
 {
   gpg_error_t err;
   int ret;
 
   ret = es_fputc (b, stream);
   if (ret == EOF)
     err = gpg_error_from_syserror ();
   else
     err = 0;
 
   return err;
 }
 
 
 /* Read a uint32 from STREAM, store it in UINT32.  */
 static gpg_error_t
 stream_read_uint32 (estream_t stream, u32 *uint32)
 {
   unsigned char buffer[4];
   size_t bytes_read;
   gpg_error_t err;
   int ret;
 
   ret = es_read (stream, buffer, sizeof (buffer), &bytes_read);
   if (ret)
     err = gpg_error_from_syserror ();
   else
     {
       if (bytes_read != sizeof (buffer))
 	err = gpg_error (GPG_ERR_EOF);
       else
 	{
 	  u32 n;
 
 	  n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]);
 	  *uint32 = n;
 	  err = 0;
 	}
     }
 
   return err;
 }
 
 /* Write the uint32 contained in UINT32 to STREAM.  */
 static gpg_error_t
 stream_write_uint32 (estream_t stream, u32 uint32)
 {
   unsigned char buffer[4];
   gpg_error_t err;
   int ret;
 
   buffer[0] = uint32 >> 24;
   buffer[1] = uint32 >> 16;
   buffer[2] = uint32 >>  8;
   buffer[3] = uint32 >>  0;
 
   ret = es_write (stream, buffer, sizeof (buffer), NULL);
   if (ret)
     err = gpg_error_from_syserror ();
   else
     err = 0;
 
   return err;
 }
 
 /* Read SIZE bytes from STREAM into BUFFER.  */
 static gpg_error_t
 stream_read_data (estream_t stream, unsigned char *buffer, size_t size)
 {
   gpg_error_t err;
   size_t bytes_read;
   int ret;
 
   ret = es_read (stream, buffer, size, &bytes_read);
   if (ret)
     err = gpg_error_from_syserror ();
   else
     {
       if (bytes_read != size)
 	err = gpg_error (GPG_ERR_EOF);
       else
 	err = 0;
     }
 
   return err;
 }
 
 /* Skip over SIZE bytes from STREAM.  */
 static gpg_error_t
 stream_read_skip (estream_t stream, size_t size)
 {
   char buffer[128];
   size_t bytes_to_read, bytes_read;
   int ret;
 
   do
     {
       bytes_to_read = size;
       if (bytes_to_read > sizeof buffer)
         bytes_to_read = sizeof buffer;
 
       ret = es_read (stream, buffer, bytes_to_read, &bytes_read);
       if (ret)
         return gpg_error_from_syserror ();
       else if (bytes_read != bytes_to_read)
         return gpg_error (GPG_ERR_EOF);
       else
         size -= bytes_to_read;
     }
   while (size);
 
   return 0;
 }
 
 
 /* Write SIZE bytes from BUFFER to STREAM.  */
 static gpg_error_t
 stream_write_data (estream_t stream, const unsigned char *buffer, size_t size)
 {
   gpg_error_t err;
   int ret;
 
   ret = es_write (stream, buffer, size, NULL);
   if (ret)
     err = gpg_error_from_syserror ();
   else
     err = 0;
 
   return err;
 }
 
 /* Read a binary string from STREAM into STRING, store size of string
    in STRING_SIZE.  Append a hidden nul so that the result may
    directly be used as a C string.  Depending on SECURE use secure
    memory for STRING.  If STRING is NULL do only a dummy read.  */
 static gpg_error_t
 stream_read_string (estream_t stream, unsigned int secure,
 		    unsigned char **string, u32 *string_size)
 {
   gpg_error_t err;
   unsigned char *buffer = NULL;
   u32 length = 0;
 
   if (string_size)
     *string_size = 0;
 
   /* Read string length.  */
   err = stream_read_uint32 (stream, &length);
   if (err)
     goto out;
 
   if (string)
     {
       /* Allocate space.  */
       if (secure)
         buffer = xtrymalloc_secure (length + 1);
       else
         buffer = xtrymalloc (length + 1);
       if (! buffer)
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
 
       /* Read data.  */
       err = stream_read_data (stream, buffer, length);
       if (err)
         goto out;
 
       /* Finalize string object.  */
       buffer[length] = 0;
       *string = buffer;
     }
   else  /* Dummy read requested.  */
     {
       err = stream_read_skip (stream, length);
       if (err)
         goto out;
     }
 
   if (string_size)
     *string_size = length;
 
  out:
 
   if (err)
     xfree (buffer);
 
   return err;
 }
 
 
 /* Read a binary string from STREAM and store it as an opaque MPI at
    R_MPI, adding 0x40 (this is the prefix for EdDSA key in OpenPGP).
    Depending on SECURE use secure memory.  If the string is too large
    for key material return an error.  */
 static gpg_error_t
 stream_read_blob (estream_t stream, unsigned int secure, gcry_mpi_t *r_mpi)
 {
   gpg_error_t err;
   unsigned char *buffer = NULL;
   u32 length = 0;
 
   *r_mpi = NULL;
 
   /* Read string length.  */
   err = stream_read_uint32 (stream, &length);
   if (err)
     goto leave;
 
   /* To avoid excessive use of secure memory we check that an MPI is
      not too large. */
   if (length > (4096/8) + 8)
     {
       log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
       err = GPG_ERR_TOO_LARGE;
       goto leave;
     }
 
   /* Allocate space.  */
   if (secure)
     buffer = xtrymalloc_secure (length+1);
   else
     buffer = xtrymalloc (length+1);
   if (!buffer)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
 
   /* Read data.  */
   err = stream_read_data (stream, buffer + 1, length);
   if (err)
     goto leave;
 
   buffer[0] = 0x40;
   *r_mpi = gcry_mpi_set_opaque (NULL, buffer, 8*(length+1));
   buffer = NULL;
 
  leave:
   xfree (buffer);
   return err;
 }
 
 
 /* Read a C-string from STREAM, store copy in STRING.  */
 static gpg_error_t
 stream_read_cstring (estream_t stream, char **string)
 {
   return stream_read_string (stream, 0, (unsigned char **)string, NULL);
 }
 
 
 /* Write a binary string from STRING of size STRING_N to STREAM.  */
 static gpg_error_t
 stream_write_string (estream_t stream,
 		     const unsigned char *string, u32 string_n)
 {
   gpg_error_t err;
 
   err = stream_write_uint32 (stream, string_n);
   if (err)
     goto out;
 
   err = stream_write_data (stream, string, string_n);
 
  out:
 
   return err;
 }
 
 /* Write a C-string from STRING to STREAM.  */
 static gpg_error_t
 stream_write_cstring (estream_t stream, const char *string)
 {
   gpg_error_t err;
 
   err = stream_write_string (stream,
 			     (const unsigned char *) string, strlen (string));
 
   return err;
 }
 
 /* Read an MPI from STREAM, store it in MPINT.  Depending on SECURE
    use secure memory.  */
 static gpg_error_t
 stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
 {
   unsigned char *mpi_data;
   u32 mpi_data_size;
   gpg_error_t err;
   gcry_mpi_t mpi;
 
   mpi_data = NULL;
 
   err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size);
   if (err)
     goto out;
 
   /* To avoid excessive use of secure memory we check that an MPI is
      not too large. */
   if (mpi_data_size > 520)
     {
       log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
       err = GPG_ERR_TOO_LARGE;
       goto out;
     }
 
   err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL);
   if (err)
     goto out;
 
   *mpint = mpi;
 
  out:
 
   xfree (mpi_data);
 
   return err;
 }
 
 /* Write the MPI contained in MPINT to STREAM.  */
 static gpg_error_t
 stream_write_mpi (estream_t stream, gcry_mpi_t mpint)
 {
   unsigned char *mpi_buffer;
   size_t mpi_buffer_n;
   gpg_error_t err;
 
   mpi_buffer = NULL;
 
   err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint);
   if (err)
     goto out;
 
   err = stream_write_string (stream, mpi_buffer, mpi_buffer_n);
 
  out:
 
   xfree (mpi_buffer);
 
   return err;
 }
 
 
 /* Copy data from SRC to DST until EOF is reached.  */
 static gpg_error_t
 stream_copy (estream_t dst, estream_t src)
 {
   char buffer[BUFSIZ];
   size_t bytes_read;
   gpg_error_t err;
   int ret;
 
   err = 0;
   while (1)
     {
       ret = es_read (src, buffer, sizeof (buffer), &bytes_read);
       if (ret || (! bytes_read))
 	{
 	  if (ret)
 	    err = gpg_error_from_syserror ();
 	  break;
 	}
       ret = es_write (dst, buffer, bytes_read, NULL);
       if (ret)
 	{
 	  err = gpg_error_from_syserror ();
 	  break;
 	}
     }
 
   return err;
 }
 
 /* Open the ssh control file and create it if not available.  With
    APPEND passed as true the file will be opened in append mode,
    otherwise in read only mode.  On success 0 is returned and a new
    control file object stored at R_CF.  On error an error code is
    returned and NULL is stored at R_CF.  */
 static gpg_error_t
 open_control_file (ssh_control_file_t *r_cf, int append)
 {
   gpg_error_t err;
   ssh_control_file_t cf;
 
   cf = xtrycalloc (1, sizeof *cf);
   if (!cf)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
 
   /* Note: As soon as we start to use non blocking functions here
      (i.e. where Pth might switch threads) we need to employ a
      mutex.  */
   cf->fname = make_filename_try (gnupg_homedir (), SSH_CONTROL_FILE_NAME, NULL);
   if (!cf->fname)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
   /* FIXME: With "a+" we are not able to check whether this will
      be created and thus the blurb needs to be written first.  */
   cf->fp = fopen (cf->fname, append? "a+":"r");
   if (!cf->fp && errno == ENOENT)
     {
       estream_t stream = es_fopen (cf->fname, "wx,mode=-rw-r");
       if (!stream)
         {
           err = gpg_error_from_syserror ();
           log_error (_("can't create '%s': %s\n"),
                      cf->fname, gpg_strerror (err));
           goto leave;
         }
       es_fputs (sshcontrolblurb, stream);
       es_fclose (stream);
       cf->fp = fopen (cf->fname, append? "a+":"r");
     }
 
   if (!cf->fp)
     {
       err = gpg_error_from_syserror ();
       log_error (_("can't open '%s': %s\n"),
                  cf->fname, gpg_strerror (err));
       goto leave;
     }
 
   err = 0;
 
  leave:
   if (err && cf)
     {
       if (cf->fp)
         fclose (cf->fp);
       xfree (cf->fname);
       xfree (cf);
     }
   else
     *r_cf = cf;
 
   return err;
 }
 
 
 static void
 rewind_control_file (ssh_control_file_t cf)
 {
   fseek (cf->fp, 0, SEEK_SET);
   cf->lnr = 0;
   clearerr (cf->fp);
 }
 
 
 static void
 close_control_file (ssh_control_file_t cf)
 {
   if (!cf)
     return;
   fclose (cf->fp);
   xfree (cf->fname);
   xfree (cf);
 }
 
 
 
 /* Read the next line from the control file and store the data in CF.
    Returns 0 on success, GPG_ERR_EOF on EOF, or other error codes. */
 static gpg_error_t
 read_control_file_item (ssh_control_file_t cf)
 {
   int c, i, n;
   char *p, *pend, line[256];
   long ttl = 0;
 
   cf->item.valid = 0;
   clearerr (cf->fp);
 
   do
     {
       if (!fgets (line, DIM(line)-1, cf->fp) )
         {
           if (feof (cf->fp))
             return gpg_error (GPG_ERR_EOF);
           return gpg_error_from_syserror ();
         }
       cf->lnr++;
 
       if (!*line || line[strlen(line)-1] != '\n')
         {
           /* Eat until end of line */
           while ( (c=getc (cf->fp)) != EOF && c != '\n')
             ;
           return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                                  : GPG_ERR_INCOMPLETE_LINE);
         }
 
       /* Allow for empty lines and spaces */
       for (p=line; spacep (p); p++)
         ;
     }
   while (!*p || *p == '\n' || *p == '#');
 
   cf->item.disabled = 0;
   if (*p == '!')
     {
       cf->item.disabled = 1;
       for (p++; spacep (p); p++)
         ;
     }
 
   for (i=0; hexdigitp (p) && i < 40; p++, i++)
     cf->item.hexgrip[i] = (*p >= 'a'? (*p & 0xdf): *p);
   cf->item.hexgrip[i] = 0;
   if (i != 40 || !(spacep (p) || *p == '\n'))
     {
       log_error ("%s:%d: invalid formatted line\n", cf->fname, cf->lnr);
       return gpg_error (GPG_ERR_BAD_DATA);
     }
 
   ttl = strtol (p, &pend, 10);
   p = pend;
   if (!(spacep (p) || *p == '\n') || (int)ttl < -1)
     {
       log_error ("%s:%d: invalid TTL value; assuming 0\n", cf->fname, cf->lnr);
       cf->item.ttl = 0;
     }
   cf->item.ttl = ttl;
 
   /* Now check for key-value pairs of the form NAME[=VALUE]. */
   cf->item.confirm = 0;
   while (*p)
     {
       for (; spacep (p) && *p != '\n'; p++)
         ;
       if (!*p || *p == '\n')
         break;
       n = strcspn (p, "= \t\n");
       if (p[n] == '=')
         {
           log_error ("%s:%d: assigning a value to a flag is not yet supported; "
                      "flag ignored\n", cf->fname, cf->lnr);
           p++;
         }
       else if (n == 7 && !memcmp (p, "confirm", 7))
         {
           cf->item.confirm = 1;
         }
       else
         log_error ("%s:%d: invalid flag '%.*s'; ignored\n",
                    cf->fname, cf->lnr, n, p);
       p += n;
     }
 
   /* log_debug ("%s:%d: grip=%s ttl=%d%s%s\n", */
   /*            cf->fname, cf->lnr, */
   /*            cf->item.hexgrip, cf->item.ttl, */
   /*            cf->item.disabled? " disabled":"", */
   /*            cf->item.confirm? " confirm":""); */
 
   cf->item.valid = 1;
   return 0; /* Okay: valid entry found.  */
 }
 
 
 
 /* Search the control file CF from the beginning until a matching
    HEXGRIP is found; return success in this case and store true at
    DISABLED if the found key has been disabled.  If R_TTL is not NULL
    a specified TTL for that key is stored there.  If R_CONFIRM is not
    NULL it is set to 1 if the key has the confirm flag set. */
 static gpg_error_t
 search_control_file (ssh_control_file_t cf, const char *hexgrip,
                      int *r_disabled, int *r_ttl, int *r_confirm)
 {
   gpg_error_t err;
 
   assert (strlen (hexgrip) == 40 );
 
   if (r_disabled)
     *r_disabled = 0;
   if (r_ttl)
     *r_ttl = 0;
   if (r_confirm)
     *r_confirm = 0;
 
   rewind_control_file (cf);
   while (!(err=read_control_file_item (cf)))
     {
       if (!cf->item.valid)
         continue; /* Should not happen.  */
       if (!strcmp (hexgrip, cf->item.hexgrip))
         break;
     }
   if (!err)
     {
       if (r_disabled)
         *r_disabled = cf->item.disabled;
       if (r_ttl)
         *r_ttl = cf->item.ttl;
       if (r_confirm)
         *r_confirm = cf->item.confirm;
     }
   return err;
 }
 
 
 
 /* Add an entry to the control file to mark the key with the keygrip
    HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
    for it.  FMTFPR is the fingerprint string.  This function is in
    general used to add a key received through the ssh-add function.
    We can assume that the user wants to allow ssh using this key. */
 static gpg_error_t
 add_control_entry (ctrl_t ctrl, ssh_key_type_spec_t *spec,
                    const char *hexgrip, gcry_sexp_t key,
                    int ttl, int confirm)
 {
   gpg_error_t err;
   ssh_control_file_t cf;
   int disabled;
   char *fpr_md5 = NULL;
   char *fpr_sha256 = NULL;
 
   (void)ctrl;
 
   err = open_control_file (&cf, 1);
   if (err)
     return err;
 
   err = search_control_file (cf, hexgrip, &disabled, NULL, NULL);
   if (err && gpg_err_code(err) == GPG_ERR_EOF)
     {
       struct tm *tp;
       time_t atime = time (NULL);
 
       err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &fpr_md5);
       if (err)
         goto out;
 
       err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &fpr_sha256);
       if (err)
         goto out;
 
       /* Not yet in the file - add it. Because the file has been
          opened in append mode, we simply need to write to it.  */
       tp = localtime (&atime);
       fprintf (cf->fp,
                ("# %s key added on: %04d-%02d-%02d %02d:%02d:%02d\n"
                 "# Fingerprints:  %s\n"
                 "#                %s\n"
                 "%s %d%s\n"),
                spec->name,
                1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
                tp->tm_hour, tp->tm_min, tp->tm_sec,
                fpr_md5, fpr_sha256, hexgrip, ttl, confirm? " confirm":"");
 
     }
  out:
   xfree (fpr_md5);
   xfree (fpr_sha256);
   close_control_file (cf);
   return 0;
 }
 
 
 /* Scan the sshcontrol file and return the TTL.  */
 static int
 ttl_from_sshcontrol (const char *hexgrip)
 {
   ssh_control_file_t cf;
   int disabled, ttl;
 
   if (!hexgrip || strlen (hexgrip) != 40)
     return 0;  /* Wrong input: Use global default.  */
 
   if (open_control_file (&cf, 0))
     return 0; /* Error: Use the global default TTL.  */
 
   if (search_control_file (cf, hexgrip, &disabled, &ttl, NULL)
       || disabled)
     ttl = 0;  /* Use the global default if not found or disabled.  */
 
   close_control_file (cf);
 
   return ttl;
 }
 
 
 /* Scan the sshcontrol file and return the confirm flag.  */
 static int
 confirm_flag_from_sshcontrol (const char *hexgrip)
 {
   ssh_control_file_t cf;
   int disabled, confirm;
 
   if (!hexgrip || strlen (hexgrip) != 40)
     return 1;  /* Wrong input: Better ask for confirmation.  */
 
   if (open_control_file (&cf, 0))
     return 1; /* Error: Better ask for confirmation.  */
 
   if (search_control_file (cf, hexgrip, &disabled, NULL, &confirm)
       || disabled)
     confirm = 0;  /* If not found or disabled, there is no reason to
                      ask for confirmation.  */
 
   close_control_file (cf);
 
   return confirm;
 }
 
 
 
 
 /* Open the ssh control file for reading.  This is a public version of
    open_control_file.  The caller must use ssh_close_control_file to
    release the returned handle.  */
 ssh_control_file_t
 ssh_open_control_file (void)
 {
   ssh_control_file_t cf;
 
   /* Then look at all the registered and non-disabled keys. */
   if (open_control_file (&cf, 0))
     return NULL;
   return cf;
 }
 
 /* Close an ssh control file handle.  This is the public version of
    close_control_file.  CF may be NULL.  */
 void
 ssh_close_control_file (ssh_control_file_t cf)
 {
   close_control_file (cf);
 }
 
 /* Read the next item from the ssh control file.  The function returns
    0 if a item was read, GPG_ERR_EOF on eof or another error value.
    R_HEXGRIP shall either be null or a BUFFER of at least 41 byte.
    R_DISABLED, R_TTLm and R_CONFIRM return flags from the control
    file; they are only set on success. */
 gpg_error_t
 ssh_read_control_file (ssh_control_file_t cf,
                        char *r_hexgrip,
                        int *r_disabled, int *r_ttl, int *r_confirm)
 {
   gpg_error_t err;
 
   do
     err = read_control_file_item (cf);
   while (!err && !cf->item.valid);
   if (!err)
     {
       if (r_hexgrip)
         strcpy (r_hexgrip, cf->item.hexgrip);
       if (r_disabled)
         *r_disabled = cf->item.disabled;
       if (r_ttl)
         *r_ttl = cf->item.ttl;
       if (r_confirm)
         *r_confirm = cf->item.confirm;
     }
   return err;
 }
 
 
 /* Search for a key with HEXGRIP in sshcontrol and return all
    info.  */
 gpg_error_t
 ssh_search_control_file (ssh_control_file_t cf,
                          const char *hexgrip,
                          int *r_disabled, int *r_ttl, int *r_confirm)
 {
   gpg_error_t err;
   int i;
   const char *s;
   char uphexgrip[41];
 
   /* We need to make sure that HEXGRIP is all uppercase.  The easiest
      way to do this and also check its length is by copying to a
      second buffer. */
   for (i=0, s=hexgrip; i < 40 && *s; s++, i++)
     uphexgrip[i] = *s >= 'a'? (*s & 0xdf): *s;
   uphexgrip[i] = 0;
   if (i != 40)
     err = gpg_error (GPG_ERR_INV_LENGTH);
   else
     err = search_control_file (cf, uphexgrip, r_disabled, r_ttl, r_confirm);
   if (gpg_err_code (err) == GPG_ERR_EOF)
     err = gpg_error (GPG_ERR_NOT_FOUND);
   return err;
 }
 
 
 
 
 /*
 
   MPI lists.
 
  */
 
 /* Free the list of MPIs MPI_LIST.  */
 static void
 mpint_list_free (gcry_mpi_t *mpi_list)
 {
   if (mpi_list)
     {
       unsigned int i;
 
       for (i = 0; mpi_list[i]; i++)
 	gcry_mpi_release (mpi_list[i]);
       xfree (mpi_list);
     }
 }
 
 /* Receive key material MPIs from STREAM according to KEY_SPEC;
    depending on SECRET expect a public key or secret key.  CERT is the
    certificate blob used if KEY_SPEC indicates the certificate format;
    it needs to be positioned to the end of the nonce.  The newly
    allocated list of MPIs is stored in MPI_LIST.  Returns usual error
    code.  */
 static gpg_error_t
 ssh_receive_mpint_list (estream_t stream, int secret,
 			ssh_key_type_spec_t *spec, estream_t cert,
                         gcry_mpi_t **mpi_list)
 {
   const char *elems_public;
   unsigned int elems_n;
   const char *elems;
   int elem_is_secret;
   gcry_mpi_t *mpis = NULL;
   gpg_error_t err = 0;
   unsigned int i;
 
   if (secret)
     elems = spec->elems_key_secret;
   else
     elems = spec->elems_key_public;
   elems_n = strlen (elems);
   elems_public = spec->elems_key_public;
 
   /* Check that either both, CERT and the WITH_CERT flag, are given or
      none of them.  */
   if (!(!!(spec->flags & SPEC_FLAG_WITH_CERT) ^ !cert))
     {
       err = gpg_error (GPG_ERR_INV_CERT_OBJ);
       goto out;
     }
 
   mpis = xtrycalloc (elems_n + 1, sizeof *mpis );
   if (!mpis)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   elem_is_secret = 0;
   for (i = 0; i < elems_n; i++)
     {
       if (secret)
 	elem_is_secret = !strchr (elems_public, elems[i]);
 
       if (cert && !elem_is_secret)
         err = stream_read_mpi (cert, elem_is_secret, &mpis[i]);
       else
         err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
       if (err)
 	goto out;
     }
 
   *mpi_list = mpis;
   mpis = NULL;
 
  out:
   if (err)
     mpint_list_free (mpis);
 
   return err;
 }
 
 
 
 /* Key modifier function for RSA.  */
 static gpg_error_t
 ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
 {
   gcry_mpi_t p;
   gcry_mpi_t q;
   gcry_mpi_t u;
 
   if (strcmp (elems, "nedupq"))
     /* Modifying only necessary for secret keys.  */
     goto out;
 
   u = mpis[3];
   p = mpis[4];
   q = mpis[5];
 
   if (gcry_mpi_cmp (p, q) > 0)
     {
       /* P shall be smaller then Q!  Swap primes.  iqmp becomes u.  */
       gcry_mpi_t tmp;
 
       tmp = mpis[4];
       mpis[4] = mpis[5];
       mpis[5] = tmp;
     }
   else
     /* U needs to be recomputed.  */
     gcry_mpi_invm (u, p, q);
 
  out:
 
   return 0;
 }
 
 /* Signature encoder function for RSA.  */
 static gpg_error_t
 ssh_signature_encoder_rsa (ssh_key_type_spec_t *spec,
                            estream_t signature_blob,
                            gcry_sexp_t s_signature)
 {
   gpg_error_t err = 0;
   gcry_sexp_t valuelist = NULL;
   gcry_sexp_t sublist = NULL;
   gcry_mpi_t sig_value = NULL;
   gcry_mpi_t *mpis = NULL;
   const char *elems;
   size_t elems_n;
   int i;
 
   unsigned char *data;
   size_t data_n;
   gcry_mpi_t s;
 
   valuelist = gcry_sexp_nth (s_signature, 1);
   if (!valuelist)
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   elems = spec->elems_signature;
   elems_n = strlen (elems);
 
   mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
   if (!mpis)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   for (i = 0; i < elems_n; i++)
     {
       sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
       if (!sublist)
 	{
 	  err = gpg_error (GPG_ERR_INV_SEXP);
 	  break;
 	}
 
       sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
       if (!sig_value)
 	{
 	  err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
 	  break;
 	}
       gcry_sexp_release (sublist);
       sublist = NULL;
 
       mpis[i] = sig_value;
     }
   if (err)
     goto out;
 
   /* RSA specific */
   s = mpis[0];
 
   err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
   if (err)
     goto out;
 
   err = stream_write_string (signature_blob, data, data_n);
   xfree (data);
 
  out:
   gcry_sexp_release (valuelist);
   gcry_sexp_release (sublist);
   mpint_list_free (mpis);
   return err;
 }
 
 
 /* Signature encoder function for DSA.  */
 static gpg_error_t
 ssh_signature_encoder_dsa (ssh_key_type_spec_t *spec,
                            estream_t signature_blob,
                            gcry_sexp_t s_signature)
 {
   gpg_error_t err = 0;
   gcry_sexp_t valuelist = NULL;
   gcry_sexp_t sublist = NULL;
   gcry_mpi_t sig_value = NULL;
   gcry_mpi_t *mpis = NULL;
   const char *elems;
   size_t elems_n;
   int i;
 
   unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS];
   unsigned char *data = NULL;
   size_t data_n;
 
   valuelist = gcry_sexp_nth (s_signature, 1);
   if (!valuelist)
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   elems = spec->elems_signature;
   elems_n = strlen (elems);
 
   mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
   if (!mpis)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   for (i = 0; i < elems_n; i++)
     {
       sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
       if (!sublist)
 	{
 	  err = gpg_error (GPG_ERR_INV_SEXP);
 	  break;
 	}
 
       sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
       if (!sig_value)
 	{
 	  err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
 	  break;
 	}
       gcry_sexp_release (sublist);
       sublist = NULL;
 
       mpis[i] = sig_value;
     }
   if (err)
     goto out;
 
   /* DSA specific code.  */
 
   /* FIXME: Why this complicated code?  Why collecting boths mpis in a
      buffer instead of writing them out one after the other?  */
   for (i = 0; i < 2; i++)
     {
       err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
       if (err)
 	break;
 
       if (data_n > SSH_DSA_SIGNATURE_PADDING)
 	{
 	  err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
 	  break;
 	}
 
       memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0,
 	      SSH_DSA_SIGNATURE_PADDING - data_n);
       memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING)
 	      + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n);
 
       xfree (data);
       data = NULL;
     }
   if (err)
     goto out;
 
   err = stream_write_string (signature_blob, buffer, sizeof (buffer));
 
  out:
   xfree (data);
   gcry_sexp_release (valuelist);
   gcry_sexp_release (sublist);
   mpint_list_free (mpis);
   return err;
 }
 
 
 /* Signature encoder function for ECDSA.  */
 static gpg_error_t
 ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
                              estream_t stream, gcry_sexp_t s_signature)
 {
   gpg_error_t err = 0;
   gcry_sexp_t valuelist = NULL;
   gcry_sexp_t sublist = NULL;
   gcry_mpi_t sig_value = NULL;
   gcry_mpi_t *mpis = NULL;
   const char *elems;
   size_t elems_n;
   int i;
 
   unsigned char *data[2] = {NULL, NULL};
   size_t data_n[2];
   size_t innerlen;
 
   valuelist = gcry_sexp_nth (s_signature, 1);
   if (!valuelist)
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   elems = spec->elems_signature;
   elems_n = strlen (elems);
 
   mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
   if (!mpis)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   for (i = 0; i < elems_n; i++)
     {
       sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
       if (!sublist)
 	{
 	  err = gpg_error (GPG_ERR_INV_SEXP);
 	  break;
 	}
 
       sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
       if (!sig_value)
 	{
 	  err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
 	  break;
 	}
       gcry_sexp_release (sublist);
       sublist = NULL;
 
       mpis[i] = sig_value;
     }
   if (err)
     goto out;
 
   /* ECDSA specific */
 
   innerlen = 0;
   for (i = 0; i < DIM(data); i++)
     {
       err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &data[i], &data_n[i], mpis[i]);
       if (err)
 	goto out;
       innerlen += 4 + data_n[i];
     }
 
   err = stream_write_uint32 (stream, innerlen);
   if (err)
     goto out;
 
   for (i = 0; i < DIM(data); i++)
     {
       err = stream_write_string (stream, data[i], data_n[i]);
       if (err)
         goto out;
     }
 
  out:
   for (i = 0; i < DIM(data); i++)
     xfree (data[i]);
   gcry_sexp_release (valuelist);
   gcry_sexp_release (sublist);
   mpint_list_free (mpis);
   return err;
 }
 
 
 /* Signature encoder function for EdDSA.  */
 static gpg_error_t
 ssh_signature_encoder_eddsa (ssh_key_type_spec_t *spec,
                              estream_t stream, gcry_sexp_t s_signature)
 {
   gpg_error_t err = 0;
   gcry_sexp_t valuelist = NULL;
   gcry_sexp_t sublist = NULL;
   const char *elems;
   size_t elems_n;
   int i;
 
   unsigned char *data[2] = {NULL, NULL};
   size_t data_n[2];
   size_t totallen = 0;
 
   valuelist = gcry_sexp_nth (s_signature, 1);
   if (!valuelist)
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   elems = spec->elems_signature;
   elems_n = strlen (elems);
 
   if (elems_n != DIM(data))
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   for (i = 0; i < DIM(data); i++)
     {
       sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
       if (!sublist)
 	{
 	  err = gpg_error (GPG_ERR_INV_SEXP);
 	  break;
 	}
 
       data[i] = gcry_sexp_nth_buffer (sublist, 1, &data_n[i]);
       if (!data[i])
 	{
 	  err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
 	  break;
 	}
       totallen += data_n[i];
       gcry_sexp_release (sublist);
       sublist = NULL;
     }
   if (err)
     goto out;
 
   err = stream_write_uint32 (stream, totallen);
   if (err)
     goto out;
 
   for (i = 0; i < DIM(data); i++)
     {
       err = stream_write_data (stream, data[i], data_n[i]);
       if (err)
         goto out;
     }
 
  out:
   for (i = 0; i < DIM(data); i++)
     xfree (data[i]);
   gcry_sexp_release (valuelist);
   gcry_sexp_release (sublist);
   return err;
 }
 
 
 /*
    S-Expressions.
  */
 
 
 /* This function constructs a new S-Expression for the key identified
    by the KEY_SPEC, SECRET, CURVE_NAME, MPIS, and COMMENT, which is to
    be stored at R_SEXP.  Returns an error code.  */
 static gpg_error_t
 sexp_key_construct (gcry_sexp_t *r_sexp,
 		    ssh_key_type_spec_t key_spec, int secret,
 		    const char *curve_name, gcry_mpi_t *mpis,
                     const char *comment)
 {
   gpg_error_t err;
   gcry_sexp_t sexp_new = NULL;
   void *formatbuf = NULL;
   void **arg_list = NULL;
   estream_t format = NULL;
   char *algo_name = NULL;
 
   if ((key_spec.flags & SPEC_FLAG_IS_EdDSA))
     {
       /* It is much easier and more readable to use a separate code
          path for EdDSA.  */
       if (!curve_name)
         err = gpg_error (GPG_ERR_INV_CURVE);
       else if (!mpis[0] || !gcry_mpi_get_flag (mpis[0], GCRYMPI_FLAG_OPAQUE))
         err = gpg_error (GPG_ERR_BAD_PUBKEY);
       else if (secret
                && (!mpis[1]
                    || !gcry_mpi_get_flag (mpis[1], GCRYMPI_FLAG_OPAQUE)))
         err = gpg_error (GPG_ERR_BAD_SECKEY);
       else if (secret)
         err = gcry_sexp_build (&sexp_new, NULL,
                                "(private-key(ecc(curve %s)"
                                "(flags eddsa)(q %m)(d %m))"
                                "(comment%s))",
                                curve_name,
                                mpis[0], mpis[1],
                                comment? comment:"");
       else
         err = gcry_sexp_build (&sexp_new, NULL,
                                "(public-key(ecc(curve %s)"
                                "(flags eddsa)(q %m))"
                                "(comment%s))",
                                curve_name,
                                mpis[0],
                                comment? comment:"");
     }
   else
     {
       const char *key_identifier[] = { "public-key", "private-key" };
       int arg_idx;
       const char *elems;
       size_t elems_n;
       unsigned int i, j;
 
       if (secret)
         elems = key_spec.elems_sexp_order;
       else
         elems = key_spec.elems_key_public;
       elems_n = strlen (elems);
 
       format = es_fopenmem (0, "a+b");
       if (!format)
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
 
       /* Key identifier, algorithm identifier, mpis, comment, and a NULL
          as a safeguard. */
       arg_list = xtrymalloc (sizeof (*arg_list) * (2 + 1 + elems_n + 1 + 1));
       if (!arg_list)
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
       arg_idx = 0;
 
       es_fputs ("(%s(%s", format);
       arg_list[arg_idx++] = &key_identifier[secret];
       algo_name = xtrystrdup (gcry_pk_algo_name (key_spec.algo));
       if (!algo_name)
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
       strlwr (algo_name);
       arg_list[arg_idx++] = &algo_name;
       if (curve_name)
         {
           es_fputs ("(curve%s)", format);
           arg_list[arg_idx++] = &curve_name;
         }
 
       for (i = 0; i < elems_n; i++)
         {
           es_fprintf (format, "(%c%%m)", elems[i]);
           if (secret)
             {
               for (j = 0; j < elems_n; j++)
                 if (key_spec.elems_key_secret[j] == elems[i])
                   break;
             }
           else
             j = i;
           arg_list[arg_idx++] = &mpis[j];
         }
       es_fputs (")(comment%s))", format);
       arg_list[arg_idx++] = &comment;
       arg_list[arg_idx] = NULL;
 
       es_putc (0, format);
       if (es_ferror (format))
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
       if (es_fclose_snatch (format, &formatbuf, NULL))
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
       format = NULL;
 
       err = gcry_sexp_build_array (&sexp_new, NULL, formatbuf, arg_list);
     }
 
   if (!err)
     *r_sexp = sexp_new;
 
  out:
   es_fclose (format);
   xfree (arg_list);
   xfree (formatbuf);
   xfree (algo_name);
 
   return err;
 }
 
 
 /* This function extracts the key from the s-expression SEXP according
    to KEY_SPEC and stores it in ssh format at (R_BLOB, R_BLOBLEN).  If
    WITH_SECRET is true, the secret key parts are also extracted if
    possible.  Returns 0 on success or an error code.  Note that data
    stored at R_BLOB must be freed using es_free!  */
 static gpg_error_t
 ssh_key_to_blob (gcry_sexp_t sexp, int with_secret,
                  ssh_key_type_spec_t key_spec,
                  void **r_blob, size_t *r_blob_size)
 {
   gpg_error_t err = 0;
   gcry_sexp_t value_list = NULL;
   gcry_sexp_t value_pair = NULL;
   char *curve_name = NULL;
   estream_t stream = NULL;
   void *blob = NULL;
   size_t blob_size;
   const char *elems, *p_elems;
   const char *data;
   size_t datalen;
 
   *r_blob = NULL;
   *r_blob_size = 0;
 
   stream = es_fopenmem (0, "r+b");
   if (!stream)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   /* Get the type of the key extpression.  */
   data = gcry_sexp_nth_data (sexp, 0, &datalen);
   if (!data)
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   if ((datalen == 10 && !strncmp (data, "public-key", 10))
       || (datalen == 21 && !strncmp (data, "protected-private-key", 21))
       || (datalen == 20 && !strncmp (data, "shadowed-private-key", 20)))
     elems = key_spec.elems_key_public;
   else if (datalen == 11 && !strncmp (data, "private-key", 11))
     elems = with_secret? key_spec.elems_key_secret : key_spec.elems_key_public;
   else
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   /* Get key value list.  */
   value_list = gcry_sexp_cadr (sexp);
   if (!value_list)
     {
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto out;
     }
 
   /* Write the ssh algorithm identifier.  */
   if ((key_spec.flags & SPEC_FLAG_IS_ECDSA))
     {
       /* Parse the "curve" parameter.  We currently expect the curve
          name for ECC and not the parameters of the curve.  This can
          easily be changed but then we need to find the curve name
          from the parameters using gcry_pk_get_curve.  */
       const char *mapped;
       const char *sshname;
 
       gcry_sexp_release (value_pair);
       value_pair = gcry_sexp_find_token (value_list, "curve", 5);
       if (!value_pair)
 	{
 	  err = gpg_error (GPG_ERR_INV_CURVE);
 	  goto out;
         }
       curve_name = gcry_sexp_nth_string (value_pair, 1);
       if (!curve_name)
 	{
 	  err = gpg_error (GPG_ERR_INV_CURVE); /* (Or out of core.)  */
 	  goto out;
         }
 
       /* Fixme: The mapping should be done by using gcry_pk_get_curve
          et al to iterate over all name aliases.  */
       if (!strcmp (curve_name, "NIST P-256"))
         mapped = "nistp256";
       else if (!strcmp (curve_name, "NIST P-384"))
         mapped = "nistp384";
       else if (!strcmp (curve_name, "NIST P-521"))
         mapped = "nistp521";
       else
         mapped = NULL;
       if (mapped)
         {
           xfree (curve_name);
           curve_name = xtrystrdup (mapped);
           if (!curve_name)
             {
               err = gpg_error_from_syserror ();
               goto out;
             }
         }
 
       sshname = ssh_identifier_from_curve_name (curve_name);
       if (!sshname)
         {
           err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
           goto out;
         }
       err = stream_write_cstring (stream, sshname);
       if (err)
         goto out;
       err = stream_write_cstring (stream, curve_name);
       if (err)
         goto out;
     }
   else
     {
       /* Note: This is also used for EdDSA.  */
       err = stream_write_cstring (stream, key_spec.ssh_identifier);
       if (err)
         goto out;
     }
 
   /* Write the parameters.  */
   for (p_elems = elems; *p_elems; p_elems++)
     {
       gcry_sexp_release (value_pair);
       value_pair = gcry_sexp_find_token (value_list, p_elems, 1);
       if (!value_pair)
 	{
 	  err = gpg_error (GPG_ERR_INV_SEXP);
 	  goto out;
 	}
       if ((key_spec.flags & SPEC_FLAG_IS_EdDSA))
         {
 
           data = gcry_sexp_nth_data (value_pair, 1, &datalen);
           if (!data)
             {
               err = gpg_error (GPG_ERR_INV_SEXP);
               goto out;
             }
           if (*p_elems == 'q' && datalen)
             { /* Remove the prefix 0x40.  */
               data++;
               datalen--;
             }
           err = stream_write_string (stream, data, datalen);
           if (err)
             goto out;
         }
       else
         {
           gcry_mpi_t mpi;
 
           /* Note that we need to use STD format; i.e. prepend a 0x00
              to indicate a positive number if the high bit is set. */
           mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD);
           if (!mpi)
             {
               err = gpg_error (GPG_ERR_INV_SEXP);
               goto out;
             }
           err = stream_write_mpi (stream, mpi);
           gcry_mpi_release (mpi);
           if (err)
             goto out;
         }
     }
 
   if (es_fclose_snatch (stream, &blob, &blob_size))
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
   stream = NULL;
 
   *r_blob = blob;
   blob = NULL;
   *r_blob_size = blob_size;
 
  out:
   gcry_sexp_release (value_list);
   gcry_sexp_release (value_pair);
   xfree (curve_name);
   es_fclose (stream);
   es_free (blob);
 
   return err;
 }
 
 
 /*
 
   Key I/O.
 
 */
 
 /* Search for a key specification entry.  If SSH_NAME is not NULL,
    search for an entry whose "ssh_name" is equal to SSH_NAME;
    otherwise, search for an entry whose algorithm is equal to ALGO.
    Store found entry in SPEC on success, return error otherwise.  */
 static gpg_error_t
 ssh_key_type_lookup (const char *ssh_name, int algo,
 		     ssh_key_type_spec_t *spec)
 {
   gpg_error_t err;
   unsigned int i;
 
   for (i = 0; i < DIM (ssh_key_types); i++)
     if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier)))
 	|| algo == ssh_key_types[i].algo)
       break;
 
   if (i == DIM (ssh_key_types))
     err = gpg_error (GPG_ERR_NOT_FOUND);
   else
     {
       *spec = ssh_key_types[i];
       err = 0;
     }
 
   return err;
 }
 
 
 /* Receive a key from STREAM, according to the key specification given
    as KEY_SPEC.  Depending on SECRET, receive a secret or a public
    key.  If READ_COMMENT is true, receive a comment string as well.
    Constructs a new S-Expression from received data and stores it in
    KEY_NEW.  Returns zero on success or an error code.  */
 static gpg_error_t
 ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
                  int read_comment, ssh_key_type_spec_t *key_spec)
 {
   gpg_error_t err;
   char *key_type = NULL;
   char *comment = NULL;
   estream_t cert = NULL;
   gcry_sexp_t key = NULL;
   ssh_key_type_spec_t spec;
   gcry_mpi_t *mpi_list = NULL;
   const char *elems;
   char *curve_name = NULL;
 
 
   err = stream_read_cstring (stream, &key_type);
   if (err)
     goto out;
 
   err = ssh_key_type_lookup (key_type, 0, &spec);
   if (err)
     goto out;
 
   if ((spec.flags & SPEC_FLAG_WITH_CERT))
     {
       /* This is an OpenSSH certificate+private key.  The certificate
          is an SSH string and which we store in an estream object. */
       unsigned char *buffer;
       u32 buflen;
       char *cert_key_type;
 
       err = stream_read_string (stream, 0, &buffer, &buflen);
       if (err)
         goto out;
       cert = es_fopenmem_init (0, "rb", buffer, buflen);
       xfree (buffer);
       if (!cert)
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
 
       /* Check that the key type matches.  */
       err = stream_read_cstring (cert, &cert_key_type);
       if (err)
         goto out;
       if (strcmp (cert_key_type, key_type) )
         {
           xfree (cert_key_type);
           log_error ("key types in received ssh certificate do not match\n");
           err = gpg_error (GPG_ERR_INV_CERT_OBJ);
           goto out;
         }
       xfree (cert_key_type);
 
       /* Skip the nonce.  */
       err = stream_read_string (cert, 0, NULL, NULL);
       if (err)
         goto out;
     }
 
   if ((spec.flags & SPEC_FLAG_IS_EdDSA))
     {
       /* The format of an EdDSA key is:
        *   string	key_type ("ssh-ed25519")
        *   string	public_key
        *   string	private_key
        *
        * Note that the private key is the concatenation of the private
        * key with the public key.  Thus there's are 64 bytes; however
        * we only want the real 32 byte private key - Libgcrypt expects
        * this.
        */
       mpi_list = xtrycalloc (3, sizeof *mpi_list);
       if (!mpi_list)
         {
           err = gpg_error_from_syserror ();
           goto out;
         }
 
       err = stream_read_blob (cert? cert : stream, 0, &mpi_list[0]);
       if (err)
         goto out;
       if (secret)
         {
           u32 len = 0;
           unsigned char *buffer;
 
           /* Read string length.  */
           err = stream_read_uint32 (stream, &len);
           if (err)
             goto out;
           if (len != 32 && len != 64)
             {
               err = gpg_error (GPG_ERR_BAD_SECKEY);
               goto out;
             }
           buffer = xtrymalloc_secure (32);
           if (!buffer)
             {
               err = gpg_error_from_syserror ();
               goto out;
             }
           err = stream_read_data (stream, buffer, 32);
           if (err)
             {
               xfree (buffer);
               goto out;
             }
           mpi_list[1] = gcry_mpi_set_opaque (NULL, buffer, 8*32);
           buffer = NULL;
           if (len == 64)
             {
               err = stream_read_skip (stream, 32);
               if (err)
                 goto out;
             }
         }
     }
   else if ((spec.flags & SPEC_FLAG_IS_ECDSA))
     {
       /* The format of an ECDSA key is:
        *   string	key_type ("ecdsa-sha2-nistp256" |
        *                          "ecdsa-sha2-nistp384" |
        *		          "ecdsa-sha2-nistp521" )
        *   string	ecdsa_curve_name
        *   string	ecdsa_public_key
        *   mpint	ecdsa_private
        *
        * Note that we use the mpint reader instead of the string
        * reader for ecsa_public_key.  For the certificate variante
        * ecdsa_curve_name+ecdsa_public_key are replaced by the
        * certificate.
        */
       unsigned char *buffer;
       const char *mapped;
 
       err = stream_read_string (cert? cert : stream, 0, &buffer, NULL);
       if (err)
         goto out;
       curve_name = buffer;
       /* Fixme: Check that curve_name matches the keytype.  */
       /* Because Libgcrypt < 1.6 has no support for the "nistpNNN"
          curve names, we need to translate them here to Libgcrypt's
          native names.  */
       if (!strcmp (curve_name, "nistp256"))
         mapped = "NIST P-256";
       else if (!strcmp (curve_name, "nistp384"))
         mapped = "NIST P-384";
       else if (!strcmp (curve_name, "nistp521"))
         mapped = "NIST P-521";
       else
         mapped = NULL;
       if (mapped)
         {
           xfree (curve_name);
           curve_name = xtrystrdup (mapped);
           if (!curve_name)
             {
               err = gpg_error_from_syserror ();
               goto out;
             }
         }
 
       err = ssh_receive_mpint_list (stream, secret, &spec, cert, &mpi_list);
       if (err)
         goto out;
     }
   else
     {
       err = ssh_receive_mpint_list (stream, secret, &spec, cert, &mpi_list);
       if (err)
         goto out;
     }
 
   if (read_comment)
     {
       err = stream_read_cstring (stream, &comment);
       if (err)
 	goto out;
     }
 
   if (secret)
     elems = spec.elems_key_secret;
   else
     elems = spec.elems_key_public;
 
   if (spec.key_modifier)
     {
       err = (*spec.key_modifier) (elems, mpi_list);
       if (err)
 	goto out;
     }
 
   if ((spec.flags & SPEC_FLAG_IS_EdDSA))
     {
       if (secret)
         {
           err = gcry_sexp_build (&key, NULL,
                                  "(private-key(ecc(curve \"Ed25519\")"
                                  "(flags eddsa)(q %m)(d %m))"
                                  "(comment%s))",
                                  mpi_list[0], mpi_list[1],
                                  comment? comment:"");
         }
       else
         {
           err = gcry_sexp_build (&key, NULL,
                                  "(public-key(ecc(curve \"Ed25519\")"
                                  "(flags eddsa)(q %m))"
                                  "(comment%s))",
                                  mpi_list[0],
                                  comment? comment:"");
         }
     }
   else
     {
       err = sexp_key_construct (&key, spec, secret, curve_name, mpi_list,
                                 comment? comment:"");
       if (err)
         goto out;
     }
 
   if (key_spec)
     *key_spec = spec;
   *key_new = key;
 
  out:
   es_fclose (cert);
   mpint_list_free (mpi_list);
   xfree (curve_name);
   xfree (key_type);
   xfree (comment);
 
   return err;
 }
 
 
 /* Write the public key from KEY to STREAM in SSH key format.  If
    OVERRIDE_COMMENT is not NULL, it will be used instead of the
    comment stored in the key.  */
 static gpg_error_t
 ssh_send_key_public (estream_t stream, gcry_sexp_t key,
                      const char *override_comment)
 {
   ssh_key_type_spec_t spec;
   int algo;
   char *comment = NULL;
   void *blob = NULL;
   size_t bloblen;
   gpg_error_t err = 0;
 
   algo = get_pk_algo_from_key (key);
   if (algo == 0)
     goto out;
 
   err = ssh_key_type_lookup (NULL, algo, &spec);
   if (err)
     goto out;
 
   err = ssh_key_to_blob (key, 0, spec, &blob, &bloblen);
   if (err)
     goto out;
 
   err = stream_write_string (stream, blob, bloblen);
   if (err)
     goto out;
 
   if (override_comment)
     err = stream_write_cstring (stream, override_comment);
   else
     {
       err = ssh_key_extract_comment (key, &comment);
       if (err)
         err = stream_write_cstring (stream, "(none)");
       else
         err = stream_write_cstring (stream, comment);
     }
   if (err)
     goto out;
 
  out:
   xfree (comment);
   es_free (blob);
 
   return err;
 }
 
 
 /* Read a public key out of BLOB/BLOB_SIZE according to the key
    specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
    Returns zero on success or an error code.  */
 static gpg_error_t
 ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
 			       gcry_sexp_t *key_public,
 			       ssh_key_type_spec_t *key_spec)
 {
   gpg_error_t err;
   estream_t blob_stream;
 
   blob_stream = es_fopenmem (0, "r+b");
   if (!blob_stream)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   err = stream_write_data (blob_stream, blob, blob_size);
   if (err)
     goto out;
 
   err = es_fseek (blob_stream, 0, SEEK_SET);
   if (err)
     goto out;
 
   err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
 
  out:
   es_fclose (blob_stream);
   return err;
 }
 
 
 
 /* This function calculates the key grip for the key contained in the
    S-Expression KEY and writes it to BUFFER, which must be large
    enough to hold it.  Returns usual error code.  */
 static gpg_error_t
 ssh_key_grip (gcry_sexp_t key, unsigned char *buffer)
 {
   if (!gcry_pk_get_keygrip (key, buffer))
     {
       gpg_error_t err = gcry_pk_testkey (key);
       return err? err : gpg_error (GPG_ERR_INTERNAL);
     }
 
   return 0;
 }
 
 
 static gpg_error_t
 card_key_list (ctrl_t ctrl, char **r_serialno, strlist_t *result)
 {
   gpg_error_t err;
 
   *r_serialno = NULL;
   *result = NULL;
 
   err = agent_card_serialno (ctrl, r_serialno, NULL);
   if (err)
     {
       if (gpg_err_code (err) != GPG_ERR_ENODEV && opt.verbose)
         log_info (_("error getting serial number of card: %s\n"),
                   gpg_strerror (err));
 
       /* Nothing available.  */
       return 0;
     }
 
   err = agent_card_cardlist (ctrl, result);
   if (err)
     {
       xfree (*r_serialno);
       *r_serialno = NULL;
     }
   return err;
 }
 
 /* Check whether a smartcard is available and whether it has a usable
    key.  Store a copy of that key at R_PK and return 0.  If no key is
    available store NULL at R_PK and return an error code.  If CARDSN
    is not NULL, a string with the serial number of the card will be
    a malloced and stored there. */
 static gpg_error_t
 card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
 {
   gpg_error_t err;
   char *authkeyid;
   char *serialno = NULL;
   unsigned char *pkbuf;
   size_t pkbuflen;
   gcry_sexp_t s_pk;
   unsigned char grip[20];
 
   *r_pk = NULL;
   if (cardsn)
     *cardsn = NULL;
 
   /* First see whether a card is available and whether the application
      is supported.  */
   err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
   if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
     {
       /* Ask for the serial number to reset the card.  */
       err = agent_card_serialno (ctrl, &serialno, NULL);
       if (err)
         {
           if (opt.verbose)
             log_info (_("error getting serial number of card: %s\n"),
                       gpg_strerror (err));
           return err;
         }
       log_info (_("detected card with S/N: %s\n"), serialno);
       err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
     }
   if (err)
     {
       log_error (_("no authentication key for ssh on card: %s\n"),
                  gpg_strerror (err));
       xfree (serialno);
       return err;
     }
 
   /* Get the S/N if we don't have it yet.  Use the fast getattr method.  */
   if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) )
     {
       log_error (_("error getting serial number of card: %s\n"),
                  gpg_strerror (err));
       xfree (authkeyid);
       return err;
     }
 
   /* Read the public key.  */
   err = agent_card_readkey (ctrl, authkeyid, &pkbuf);
   if (err)
     {
       if (opt.verbose)
         log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
       xfree (serialno);
       xfree (authkeyid);
       return err;
     }
 
   pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
   err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen);
   if (err)
     {
       log_error ("failed to build S-Exp from received card key: %s\n",
                  gpg_strerror (err));
       xfree (pkbuf);
       xfree (serialno);
       xfree (authkeyid);
       return err;
     }
 
   err = ssh_key_grip (s_pk, grip);
   if (err)
     {
       log_debug ("error computing keygrip from received card key: %s\n",
 		 gcry_strerror (err));
       xfree (pkbuf);
       gcry_sexp_release (s_pk);
       xfree (serialno);
       xfree (authkeyid);
       return err;
     }
 
   if ( agent_key_available (grip) )
     {
       /* (Shadow)-key is not available in our key storage.  */
       err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0);
       if (err)
         {
           xfree (pkbuf);
           gcry_sexp_release (s_pk);
           xfree (serialno);
           xfree (authkeyid);
           return err;
         }
     }
 
   if (cardsn)
     {
       char *dispsn;
 
       /* If the card handler is able to return a short serialnumber,
          use that one, else use the complete serialno. */
       if (!agent_card_getattr (ctrl, "$DISPSERIALNO", &dispsn))
         {
           *cardsn = xtryasprintf ("cardno:%s", dispsn);
           xfree (dispsn);
         }
       else
         *cardsn = xtryasprintf ("cardno:%s", serialno);
       if (!*cardsn)
         {
           err = gpg_error_from_syserror ();
           xfree (pkbuf);
           gcry_sexp_release (s_pk);
           xfree (serialno);
           xfree (authkeyid);
           return err;
         }
     }
 
   xfree (pkbuf);
   xfree (serialno);
   xfree (authkeyid);
   *r_pk = s_pk;
   return 0;
 }
 
 
 
 
 /*
 
   Request handler.  Each handler is provided with a CTRL context, a
   REQUEST object and a RESPONSE object.  The actual request is to be
   read from REQUEST, the response needs to be written to RESPONSE.
 
 */
 
 
 /* Handler for the "request_identities" command.  */
 static gpg_error_t
 ssh_handler_request_identities (ctrl_t ctrl,
                                 estream_t request, estream_t response)
 {
   u32 key_counter;
   estream_t key_blobs;
   gcry_sexp_t key_public;
   gpg_error_t err;
   int ret;
   ssh_control_file_t cf = NULL;
   gpg_error_t ret_err;
 
   (void)request;
 
   /* Prepare buffer stream.  */
 
   key_public = NULL;
   key_counter = 0;
 
   key_blobs = es_fopenmem (0, "r+b");
   if (! key_blobs)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   /* First check whether a key is currently available in the card
      reader - this should be allowed even without being listed in
      sshcontrol. */
 
   if (!opt.disable_scdaemon)
     {
       char *serialno;
       strlist_t card_list, sl;
 
       err = card_key_list (ctrl, &serialno, &card_list);
       if (err)
         {
           if (opt.verbose)
             log_info (_("error getting list of cards: %s\n"),
                       gpg_strerror (err));
           goto scd_out;
         }
 
       for (sl = card_list; sl; sl = sl->next)
         {
           char *serialno0;
           char *cardsn;
 
           err = agent_card_serialno (ctrl, &serialno0, sl->d);
           if (err)
             {
               if (opt.verbose)
                 log_info (_("error getting serial number of card: %s\n"),
                           gpg_strerror (err));
               continue;
             }
 
           xfree (serialno0);
           if (card_key_available (ctrl, &key_public, &cardsn))
             continue;
 
           err = ssh_send_key_public (key_blobs, key_public, cardsn);
           gcry_sexp_release (key_public);
           key_public = NULL;
           xfree (cardsn);
           if (err)
             {
               xfree (serialno);
               free_strlist (card_list);
               goto out;
             }
 
           key_counter++;
         }
 
       xfree (serialno);
       free_strlist (card_list);
     }
 
  scd_out:
   /* Then look at all the registered and non-disabled keys. */
   err = open_control_file (&cf, 0);
   if (err)
     goto out;
 
   while (!read_control_file_item (cf))
     {
       unsigned char grip[20];
 
       if (!cf->item.valid)
         continue; /* Should not happen.  */
       if (cf->item.disabled)
         continue;
       assert (strlen (cf->item.hexgrip) == 40);
       hex2bin (cf->item.hexgrip, grip, sizeof (grip));
 
       err = agent_public_key_from_file (ctrl, grip, &key_public);
       if (err)
         {
           log_error ("%s:%d: key '%s' skipped: %s\n",
                      cf->fname, cf->lnr, cf->item.hexgrip,
                      gpg_strerror (err));
           continue;
         }
 
       err = ssh_send_key_public (key_blobs, key_public, NULL);
       if (err)
         goto out;
       gcry_sexp_release (key_public);
       key_public = NULL;
 
       key_counter++;
     }
   err = 0;
 
   ret = es_fseek (key_blobs, 0, SEEK_SET);
   if (ret)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
  out:
   /* Send response.  */
 
   gcry_sexp_release (key_public);
 
   if (!err)
     {
       ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
       if (!ret_err)
         ret_err = stream_write_uint32 (response, key_counter);
       if (!ret_err)
         ret_err = stream_copy (response, key_blobs);
     }
   else
     {
       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
     }
 
   es_fclose (key_blobs);
   close_control_file (cf);
 
   return ret_err;
 }
 
 
 /* This function hashes the data contained in DATA of size DATA_N
    according to the message digest algorithm specified by MD_ALGORITHM
    and writes the message digest to HASH, which needs to large enough
    for the digest.  */
 static gpg_error_t
 data_hash (unsigned char *data, size_t data_n,
 	   int md_algorithm, unsigned char *hash)
 {
   gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
 
   return 0;
 }
 
 
 /* This function signs the data described by CTRL. If HASH is not
    NULL, (HASH,HASHLEN) overrides the hash stored in CTRL.  This is to
    allow the use of signature algorithms that implement the hashing
    internally (e.g. Ed25519).  On success the created signature is
    stored in ssh format at R_SIG and it's size at R_SIGLEN; the caller
    must use es_free to releaase this memory.  */
 static gpg_error_t
 data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec,
            const void *hash, size_t hashlen,
 	   unsigned char **r_sig, size_t *r_siglen)
 {
   gpg_error_t err;
   gcry_sexp_t signature_sexp = NULL;
   estream_t stream = NULL;
   void *blob = NULL;
   size_t bloblen;
   char hexgrip[40+1];
 
   *r_sig = NULL;
   *r_siglen = 0;
 
   /* Quick check to see whether we have a valid keygrip and convert it
      to hex.  */
   if (!ctrl->have_keygrip)
     {
       err = gpg_error (GPG_ERR_NO_SECKEY);
       goto out;
     }
   bin2hex (ctrl->keygrip, 20, hexgrip);
 
   /* Ask for confirmation if needed.  */
   if (confirm_flag_from_sshcontrol (hexgrip))
     {
       gcry_sexp_t key;
       char *fpr, *prompt;
       char *comment = NULL;
 
       err = agent_raw_key_from_file (ctrl, ctrl->keygrip, &key);
       if (err)
         goto out;
       err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &fpr);
       if (!err)
         {
           gcry_sexp_t tmpsxp = gcry_sexp_find_token (key, "comment", 0);
           if (tmpsxp)
             comment = gcry_sexp_nth_string (tmpsxp, 1);
           gcry_sexp_release (tmpsxp);
         }
       gcry_sexp_release (key);
       if (err)
         goto out;
       prompt = xtryasprintf (L_("An ssh process requested the use of key%%0A"
                                 "  %s%%0A"
                                 "  (%s)%%0A"
                                 "Do you want to allow this?"),
                              fpr, comment? comment:"");
       xfree (fpr);
       gcry_free (comment);
       err = agent_get_confirmation (ctrl, prompt, L_("Allow"), L_("Deny"), 0);
       xfree (prompt);
       if (err)
         goto out;
     }
 
   /* Create signature.  */
   ctrl->use_auth_call = 1;
   err = agent_pksign_do (ctrl, NULL,
                          L_("Please enter the passphrase "
                             "for the ssh key%%0A  %F%%0A  (%c)"),
                          &signature_sexp,
                          CACHE_MODE_SSH, ttl_from_sshcontrol,
                          hash, hashlen);
   ctrl->use_auth_call = 0;
   if (err)
     goto out;
 
   stream = es_fopenmem (0, "r+b");
   if (!stream)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   err = stream_write_cstring (stream, spec->ssh_identifier);
   if (err)
     goto out;
 
   err = spec->signature_encoder (spec, stream, signature_sexp);
   if (err)
     goto out;
 
   err = es_fclose_snatch (stream, &blob, &bloblen);
   if (err)
     goto out;
   stream = NULL;
 
   *r_sig = blob; blob = NULL;
   *r_siglen = bloblen;
 
  out:
   xfree (blob);
   es_fclose (stream);
   gcry_sexp_release (signature_sexp);
 
   return err;
 }
 
 
 /* Handler for the "sign_request" command.  */
 static gpg_error_t
 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
 {
   gcry_sexp_t key = NULL;
   ssh_key_type_spec_t spec;
   unsigned char hash[MAX_DIGEST_LEN];
   unsigned int hash_n;
   unsigned char key_grip[20];
   unsigned char *key_blob = NULL;
   u32 key_blob_size;
   unsigned char *data = NULL;
   unsigned char *sig = NULL;
   size_t sig_n;
   u32 data_size;
   u32 flags;
   gpg_error_t err;
   gpg_error_t ret_err;
   int hash_algo;
 
   /* Receive key.  */
 
   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
   if (err)
     goto out;
 
   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
   if (err)
     goto out;
 
   /* Receive data to sign.  */
   err = stream_read_string (request, 0, &data, &data_size);
   if (err)
     goto out;
 
   /* FIXME?  */
   err = stream_read_uint32 (request, &flags);
   if (err)
     goto out;
 
   hash_algo = spec.hash_algo;
   if (!hash_algo)
     hash_algo = GCRY_MD_SHA1;  /* Use the default.  */
   ctrl->digest.algo = hash_algo;
   if ((spec.flags & SPEC_FLAG_USE_PKCS1V2))
     ctrl->digest.raw_value = 0;
   else
     ctrl->digest.raw_value = 1;
 
   /* Calculate key grip.  */
   err = ssh_key_grip (key, key_grip);
   if (err)
     goto out;
   ctrl->have_keygrip = 1;
   memcpy (ctrl->keygrip, key_grip, 20);
 
   /* Hash data unless we use EdDSA.  */
   if ((spec.flags & SPEC_FLAG_IS_EdDSA))
     {
       ctrl->digest.valuelen = 0;
     }
   else
     {
       hash_n = gcry_md_get_algo_dlen (hash_algo);
       if (!hash_n)
         {
           err = gpg_error (GPG_ERR_INTERNAL);
           goto out;
         }
       err = data_hash (data, data_size, hash_algo, hash);
       if (err)
         goto out;
       memcpy (ctrl->digest.value, hash, hash_n);
       ctrl->digest.valuelen = hash_n;
     }
 
   /* Sign data.  */
   if ((spec.flags & SPEC_FLAG_IS_EdDSA))
     err = data_sign (ctrl, &spec, data, data_size, &sig, &sig_n);
   else
     err = data_sign (ctrl, &spec, NULL, 0, &sig, &sig_n);
 
  out:
   /* Done.  */
   if (!err)
     {
       ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
       if (ret_err)
 	goto leave;
       ret_err = stream_write_string (response, sig, sig_n);
       if (ret_err)
 	goto leave;
     }
   else
     {
       log_error ("ssh sign request failed: %s <%s>\n",
                  gpg_strerror (err), gpg_strsource (err));
       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
       if (ret_err)
 	goto leave;
     }
 
  leave:
 
   gcry_sexp_release (key);
   xfree (key_blob);
   xfree (data);
   es_free (sig);
 
   return ret_err;
 }
 
 
 /* This function extracts the comment contained in the key
    s-expression KEY and stores a copy in COMMENT.  Returns usual error
    code.  */
 static gpg_error_t
 ssh_key_extract_comment (gcry_sexp_t key, char **r_comment)
 {
   gcry_sexp_t comment_list;
 
   *r_comment = NULL;
 
   comment_list = gcry_sexp_find_token (key, "comment", 0);
   if (!comment_list)
     return gpg_error (GPG_ERR_INV_SEXP);
 
   *r_comment = gcry_sexp_nth_string (comment_list, 1);
   gcry_sexp_release (comment_list);
   if (!*r_comment)
     return gpg_error (GPG_ERR_INV_SEXP);
 
   return 0;
 }
 
 
 /* This function converts the key contained in the S-Expression KEY
    into a buffer, which is protected by the passphrase PASSPHRASE.
    If PASSPHRASE is the empty passphrase, the key is not protected.
    Returns usual error code.  */
 static gpg_error_t
 ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
 			     unsigned char **buffer, size_t *buffer_n)
 {
   unsigned char *buffer_new;
   unsigned int buffer_new_n;
   gpg_error_t err;
 
   buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
   buffer_new = xtrymalloc_secure (buffer_new_n);
   if (! buffer_new)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
   /* FIXME: guarantee?  */
 
   if (*passphrase)
     err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1);
   else
     {
       /* The key derivation function does not support zero length
        * strings.  Store key unprotected if the user wishes so.  */
       *buffer = buffer_new;
       *buffer_n = buffer_new_n;
       buffer_new = NULL;
       err = 0;
     }
 
  out:
 
   xfree (buffer_new);
 
   return err;
 }
 
 
 
 /* Callback function to compare the first entered PIN with the one
    currently being entered. */
 static gpg_error_t
 reenter_compare_cb (struct pin_entry_info_s *pi)
 {
   const char *pin1 = pi->check_cb_arg;
 
   if (!strcmp (pin1, pi->pin))
     return 0; /* okay */
   return gpg_error (GPG_ERR_BAD_PASSPHRASE);
 }
 
 
 /* Store the ssh KEY into our local key storage and protect it after
    asking for a passphrase.  Cache that passphrase.  TTL is the
    maximum caching time for that key.  If the key already exists in
    our key storage, don't do anything.  When entering a key also add
    an entry to the sshcontrol file.  */
 static gpg_error_t
 ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
                        gcry_sexp_t key, int ttl, int confirm)
 {
   gpg_error_t err;
   unsigned char key_grip_raw[20];
   char key_grip[41];
   unsigned char *buffer = NULL;
   size_t buffer_n;
   char *description = NULL;
   const char *description2 = L_("Please re-enter this passphrase");
   char *comment = NULL;
   char *key_fpr = NULL;
   const char *initial_errtext = NULL;
   struct pin_entry_info_s *pi = NULL;
   struct pin_entry_info_s *pi2 = NULL;
 
   err = ssh_key_grip (key, key_grip_raw);
   if (err)
     goto out;
 
   bin2hex (key_grip_raw, 20, key_grip);
 
   err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &key_fpr);
   if (err)
     goto out;
 
   /* Check whether the key is already in our key storage.  Don't do
      anything then besides (re-)adding it to sshcontrol.  */
   if ( !agent_key_available (key_grip_raw) )
     goto key_exists; /* Yes, key is available.  */
 
   err = ssh_key_extract_comment (key, &comment);
   if (err)
     goto out;
 
   if ( asprintf (&description,
                  L_("Please enter a passphrase to protect"
                     " the received secret key%%0A"
                     "   %s%%0A"
                     "   %s%%0A"
                     "within gpg-agent's key storage"),
                  key_fpr, comment ? comment : "") < 0)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
   if (!pi)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
   pi2 = gcry_calloc_secure (1, sizeof (*pi2) + MAX_PASSPHRASE_LEN + 1);
   if (!pi2)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
   pi->max_length = MAX_PASSPHRASE_LEN + 1;
   pi->max_tries = 1;
   pi->with_repeat = 1;
   pi2->max_length = MAX_PASSPHRASE_LEN + 1;
   pi2->max_tries = 1;
   pi2->check_cb = reenter_compare_cb;
   pi2->check_cb_arg = pi->pin;
 
  next_try:
   err = agent_askpin (ctrl, description, NULL, initial_errtext, pi, NULL, 0);
   initial_errtext = NULL;
   if (err)
     goto out;
 
   /* Unless the passphrase is empty or the pinentry told us that
      it already did the repetition check, ask to confirm it.  */
   if (*pi->pin && !pi->repeat_okay)
     {
       err = agent_askpin (ctrl, description2, NULL, NULL, pi2, NULL, 0);
       if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
 	{ /* The re-entered one did not match and the user did not
 	     hit cancel. */
 	  initial_errtext = L_("does not match - try again");
 	  goto next_try;
 	}
     }
 
   err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
   if (err)
     goto out;
 
   /* Store this key to our key storage.  */
   err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
   if (err)
     goto out;
 
   /* Cache this passphrase. */
   err = agent_put_cache (key_grip, CACHE_MODE_SSH, pi->pin, ttl);
   if (err)
     goto out;
 
  key_exists:
   /* And add an entry to the sshcontrol file.  */
   err = add_control_entry (ctrl, spec, key_grip, key, ttl, confirm);
 
 
  out:
   if (pi2 && pi2->max_length)
     wipememory (pi2->pin, pi2->max_length);
   xfree (pi2);
   if (pi && pi->max_length)
     wipememory (pi->pin, pi->max_length);
   xfree (pi);
   xfree (buffer);
   xfree (comment);
   xfree (key_fpr);
   xfree (description);
 
   return err;
 }
 
 
 /* This function removes the key contained in the S-Expression KEY
    from the local key storage, in case it exists there.  Returns usual
    error code.  FIXME: this function is a stub.  */
 static gpg_error_t
 ssh_identity_drop (gcry_sexp_t key)
 {
   unsigned char key_grip[21] = { 0 };
   gpg_error_t err;
 
   err = ssh_key_grip (key, key_grip);
   if (err)
     goto out;
 
   key_grip[sizeof (key_grip) - 1] = 0;
 
   /* FIXME: What to do here - forgetting the passphrase or deleting
      the key from key cache?  */
 
  out:
 
   return err;
 }
 
 /* Handler for the "add_identity" command.  */
 static gpg_error_t
 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
 {
   gpg_error_t ret_err;
   ssh_key_type_spec_t spec;
   gpg_error_t err;
   gcry_sexp_t key;
   unsigned char b;
   int confirm;
   int ttl;
 
   confirm = 0;
   key = NULL;
   ttl = 0;
 
   /* FIXME?  */
   err = ssh_receive_key (request, &key, 1, 1, &spec);
   if (err)
     goto out;
 
   while (1)
     {
       err = stream_read_byte (request, &b);
       if (gpg_err_code (err) == GPG_ERR_EOF)
 	{
 	  err = 0;
 	  break;
 	}
 
       switch (b)
 	{
 	case SSH_OPT_CONSTRAIN_LIFETIME:
 	  {
 	    u32 n = 0;
 
 	    err = stream_read_uint32 (request, &n);
 	    if (! err)
 	      ttl = n;
 	    break;
 	  }
 
 	case SSH_OPT_CONSTRAIN_CONFIRM:
 	  {
 	    confirm = 1;
 	    break;
 	  }
 
 	default:
 	  /* FIXME: log/bad?  */
 	  break;
 	}
     }
   if (err)
     goto out;
 
   err = ssh_identity_register (ctrl, &spec, key, ttl, confirm);
 
  out:
 
   gcry_sexp_release (key);
 
   if (! err)
     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
   else
     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
 
   return ret_err;
 }
 
 /* Handler for the "remove_identity" command.  */
 static gpg_error_t
 ssh_handler_remove_identity (ctrl_t ctrl,
 			     estream_t request, estream_t response)
 {
   unsigned char *key_blob;
   u32 key_blob_size;
   gcry_sexp_t key;
   gpg_error_t ret_err;
   gpg_error_t err;
 
   (void)ctrl;
 
   /* Receive key.  */
 
   key_blob = NULL;
   key = NULL;
 
   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
   if (err)
     goto out;
 
   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
   if (err)
     goto out;
 
   err = ssh_identity_drop (key);
 
  out:
 
   xfree (key_blob);
   gcry_sexp_release (key);
 
   if (! err)
     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
   else
     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
 
   return ret_err;
 }
 
 /* FIXME: stub function.  Actually useful?  */
 static gpg_error_t
 ssh_identities_remove_all (void)
 {
   gpg_error_t err;
 
   err = 0;
 
   /* FIXME: shall we remove _all_ cache entries or only those
      registered through the ssh-agent protocol?  */
 
   return err;
 }
 
 /* Handler for the "remove_all_identities" command.  */
 static gpg_error_t
 ssh_handler_remove_all_identities (ctrl_t ctrl,
 				   estream_t request, estream_t response)
 {
   gpg_error_t ret_err;
   gpg_error_t err;
 
   (void)ctrl;
   (void)request;
 
   err = ssh_identities_remove_all ();
 
   if (! err)
     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
   else
     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
 
   return ret_err;
 }
 
 /* Lock agent?  FIXME: stub function.  */
 static gpg_error_t
 ssh_lock (void)
 {
   gpg_error_t err;
 
   /* FIXME */
   log_error ("ssh-agent's lock command is not implemented\n");
   err = 0;
 
   return err;
 }
 
 /* Unock agent?  FIXME: stub function.  */
 static gpg_error_t
 ssh_unlock (void)
 {
   gpg_error_t err;
 
   log_error ("ssh-agent's unlock command is not implemented\n");
   err = 0;
 
   return err;
 }
 
 /* Handler for the "lock" command.  */
 static gpg_error_t
 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
 {
   gpg_error_t ret_err;
   gpg_error_t err;
 
   (void)ctrl;
   (void)request;
 
   err = ssh_lock ();
 
   if (! err)
     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
   else
     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
 
   return ret_err;
 }
 
 /* Handler for the "unlock" command.  */
 static gpg_error_t
 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
 {
   gpg_error_t ret_err;
   gpg_error_t err;
 
   (void)ctrl;
   (void)request;
 
   err = ssh_unlock ();
 
   if (! err)
     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
   else
     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
 
   return ret_err;
 }
 
 
 
 /* Return the request specification for the request identified by TYPE
    or NULL in case the requested request specification could not be
    found.  */
 static const ssh_request_spec_t *
 request_spec_lookup (int type)
 {
   const ssh_request_spec_t *spec;
   unsigned int i;
 
   for (i = 0; i < DIM (request_specs); i++)
     if (request_specs[i].type == type)
       break;
   if (i == DIM (request_specs))
     {
       if (opt.verbose)
         log_info ("ssh request %u is not supported\n", type);
       spec = NULL;
     }
   else
     spec = request_specs + i;
 
   return spec;
 }
 
 /* Process a single request.  The request is read from and the
    response is written to STREAM_SOCK.  Uses CTRL as context.  Returns
    zero in case of success, non zero in case of failure.  */
 static int
 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
 {
   const ssh_request_spec_t *spec;
   estream_t response = NULL;
   estream_t request = NULL;
   unsigned char request_type;
   gpg_error_t err;
   int send_err = 0;
   int ret;
   unsigned char *request_data = NULL;
   u32 request_data_size;
   u32 response_size;
 
   /* Create memory streams for request/response data.  The entire
      request will be stored in secure memory, since it might contain
      secret key material.  The response does not have to be stored in
      secure memory, since we never give out secret keys.
 
      Note: we only have little secure memory, but there is NO
      possibility of DoS here; only trusted clients are allowed to
      connect to the agent.  What could happen is that the agent
      returns out-of-secure-memory errors on requests in case the
      agent's owner floods his own agent with many large messages.
      -moritz */
 
   /* Retrieve request.  */
   err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
   if (err)
     goto out;
 
   if (opt.verbose > 1)
     log_info ("received ssh request of length %u\n",
               (unsigned int)request_data_size);
 
   if (! request_data_size)
     {
       send_err = 1;
       goto out;
       /* Broken request; FIXME.  */
     }
 
   request_type = request_data[0];
   spec = request_spec_lookup (request_type);
   if (! spec)
     {
       send_err = 1;
       goto out;
       /* Unknown request; FIXME.  */
     }
 
   if (spec->secret_input)
     request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+b");
   else
     request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+b");
   if (! request)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
   ret = es_setvbuf (request, NULL, _IONBF, 0);
   if (ret)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
   err = stream_write_data (request, request_data + 1, request_data_size - 1);
   if (err)
     goto out;
   es_rewind (request);
 
   response = es_fopenmem (0, "r+b");
   if (! response)
     {
       err = gpg_error_from_syserror ();
       goto out;
     }
 
   if (opt.verbose)
     log_info ("ssh request handler for %s (%u) started\n",
 	       spec->identifier, spec->type);
 
   err = (*spec->handler) (ctrl, request, response);
 
   if (opt.verbose)
     {
       if (err)
         log_info ("ssh request handler for %s (%u) failed: %s\n",
                   spec->identifier, spec->type, gpg_strerror (err));
       else
         log_info ("ssh request handler for %s (%u) ready\n",
                   spec->identifier, spec->type);
     }
 
   if (err)
     {
       send_err = 1;
       goto out;
     }
 
   response_size = es_ftell (response);
   if (opt.verbose > 1)
     log_info ("sending ssh response of length %u\n",
               (unsigned int)response_size);
 
   err = es_fseek (response, 0, SEEK_SET);
   if (err)
     {
       send_err = 1;
       goto out;
     }
 
   err = stream_write_uint32 (stream_sock, response_size);
   if (err)
     {
       send_err = 1;
       goto out;
     }
 
   err = stream_copy (stream_sock, response);
   if (err)
     goto out;
 
   err = es_fflush (stream_sock);
   if (err)
     goto out;
 
  out:
 
   if (err && es_feof (stream_sock))
     log_error ("error occurred while processing request: %s\n",
 	       gpg_strerror (err));
 
   if (send_err)
     {
       if (opt.verbose > 1)
         log_info ("sending ssh error response\n");
       err = stream_write_uint32 (stream_sock, 1);
       if (err)
 	goto leave;
       err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
       if (err)
 	goto leave;
     }
 
  leave:
 
   es_fclose (request);
   es_fclose (response);
   xfree (request_data);
 
   return !!err;
 }
 
 
 /* Return the peer's pid.  */
 static unsigned long
 get_client_pid (int fd)
 {
   pid_t client_pid = (pid_t)0;
 
 #ifdef SO_PEERCRED
   {
 #ifdef HAVE_STRUCT_SOCKPEERCRED_PID
     struct sockpeercred cr;
 #else
     struct ucred cr;
 #endif
     socklen_t cl = sizeof cr;
 
     if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
       {
 #if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID)
         client_pid = cr.pid;
 #elif defined (HAVE_STRUCT_UCRED_CR_PID)
         client_pid = cr.cr_pid;
 #else
 #error "Unknown SO_PEERCRED struct"
 #endif
       }
   }
 #elif defined (LOCAL_PEERPID)
   {
     socklen_t len = sizeof (pid_t);
 
     getsockopt (fd, SOL_LOCAL, LOCAL_PEERPID, &client_pid, &len);
   }
 #elif defined (LOCAL_PEEREID)
   {
     struct unpcbid unp;
     socklen_t unpl = sizeof unp;
 
     if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
       client_pid = unp.unp_pid;
   }
 #elif defined (HAVE_GETPEERUCRED)
   {
     ucred_t *ucred = NULL;
 
     if (getpeerucred (fd, &ucred) != -1)
       {
         client_pid= ucred_getpid (ucred);
         ucred_free (ucred);
       }
   }
 #else
   (void)fd;
 #endif
 
   return (unsigned long)client_pid;
 }
 
 
 /* Start serving client on SOCK_CLIENT.  */
 void
 start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
 {
   estream_t stream_sock = NULL;
   gpg_error_t err;
   int ret;
 
   err = agent_copy_startup_env (ctrl);
   if (err)
     goto out;
 
   ctrl->client_pid = get_client_pid (FD2INT(sock_client));
 
   /* Create stream from socket.  */
   stream_sock = es_fdopen (FD2INT(sock_client), "r+");
   if (!stream_sock)
     {
       err = gpg_error_from_syserror ();
       log_error (_("failed to create stream from socket: %s\n"),
 		 gpg_strerror (err));
       goto out;
     }
   /* We have to disable the estream buffering, because the estream
      core doesn't know about secure memory.  */
   ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
   if (ret)
     {
       err = gpg_error_from_syserror ();
       log_error ("failed to disable buffering "
                  "on socket stream: %s\n", gpg_strerror (err));
       goto out;
     }
 
   /* Main processing loop. */
   while ( !ssh_request_process (ctrl, stream_sock) )
     {
       /* Check whether we have reached EOF before trying to read
 	 another request.  */
       int c;
 
       c = es_fgetc (stream_sock);
       if (c == EOF)
         break;
       es_ungetc (c, stream_sock);
     }
 
   /* Reset the SCD in case it has been used. */
   agent_reset_scd (ctrl);
 
 
  out:
   if (stream_sock)
     es_fclose (stream_sock);
 }
 
 
 #ifdef HAVE_W32_SYSTEM
 /* Serve one ssh-agent request.  This is used for the Putty support.
    REQUEST is the mmapped memory which may be accessed up to a
    length of MAXREQLEN.  Returns 0 on success which also indicates
    that a valid SSH response message is now in REQUEST.  */
 int
 serve_mmapped_ssh_request (ctrl_t ctrl,
                            unsigned char *request, size_t maxreqlen)
 {
   gpg_error_t err;
   int send_err = 0;
   int valid_response = 0;
   const ssh_request_spec_t *spec;
   u32 msglen;
   estream_t request_stream, response_stream;
 
   if (agent_copy_startup_env (ctrl))
     goto leave; /* Error setting up the environment.  */
 
   if (maxreqlen < 5)
     goto leave; /* Caller error.  */
 
   msglen = uint32_construct (request[0], request[1], request[2], request[3]);
   if (msglen < 1 || msglen > maxreqlen - 4)
     {
       log_error ("ssh message len (%u) out of range", (unsigned int)msglen);
       goto leave;
     }
 
   spec = request_spec_lookup (request[4]);
   if (!spec)
     {
       send_err = 1;  /* Unknown request type.  */
       goto leave;
     }
 
   /* Create a stream object with the data part of the request.  */
   if (spec->secret_input)
     request_stream = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
   else
     request_stream = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
   if (!request_stream)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
   /* We have to disable the estream buffering, because the estream
      core doesn't know about secure memory.  */
   if (es_setvbuf (request_stream, NULL, _IONBF, 0))
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
   /* Copy the request to the stream but omit the request type.  */
   err = stream_write_data (request_stream, request + 5, msglen - 1);
   if (err)
     goto leave;
   es_rewind (request_stream);
 
   response_stream = es_fopenmem (0, "r+b");
   if (!response_stream)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
 
   if (opt.verbose)
     log_info ("ssh request handler for %s (%u) started\n",
 	       spec->identifier, spec->type);
 
   err = (*spec->handler) (ctrl, request_stream, response_stream);
 
   if (opt.verbose)
     {
       if (err)
         log_info ("ssh request handler for %s (%u) failed: %s\n",
                   spec->identifier, spec->type, gpg_strerror (err));
       else
         log_info ("ssh request handler for %s (%u) ready\n",
                   spec->identifier, spec->type);
     }
 
   es_fclose (request_stream);
   request_stream = NULL;
 
   if (err)
     {
       send_err = 1;
       goto leave;
     }
 
   /* Put the response back into the mmapped buffer.  */
   {
     void *response_data;
     size_t response_size;
 
     /* NB: In contrast to the request-stream, the response stream
        includes the message type byte.  */
     if (es_fclose_snatch (response_stream, &response_data, &response_size))
       {
         log_error ("snatching ssh response failed: %s",
                    gpg_strerror (gpg_error_from_syserror ()));
         send_err = 1; /* Ooops.  */
         goto leave;
       }
 
     if (opt.verbose > 1)
       log_info ("sending ssh response of length %u\n",
                 (unsigned int)response_size);
     if (response_size > maxreqlen - 4)
       {
         log_error ("invalid length of the ssh response: %s",
                    gpg_strerror (GPG_ERR_INTERNAL));
         es_free (response_data);
         send_err = 1;
         goto leave;
       }
 
     request[0] = response_size >> 24;
     request[1] = response_size >> 16;
     request[2] = response_size >>  8;
     request[3] = response_size >>  0;
     memcpy (request+4, response_data, response_size);
     es_free (response_data);
     valid_response = 1;
   }
 
  leave:
   if (send_err)
     {
       request[0] = 0;
       request[1] = 0;
       request[2] = 0;
       request[3] = 1;
       request[4] = SSH_RESPONSE_FAILURE;
       valid_response = 1;
     }
 
   /* Reset the SCD in case it has been used. */
   agent_reset_scd (ctrl);
 
   return valid_response? 0 : -1;
 }
 #endif /*HAVE_W32_SYSTEM*/
diff --git a/configure.ac b/configure.ac
index 424ce7be1..420af92f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,2055 +1,2055 @@
 # configure.ac - for GnuPG 2.1
 # Copyright (C) 1998-2017 Free Software Foundation, Inc.
 # Copyright (C) 1998-2017 Werner Koch
 #
 # This file is part of GnuPG.
 #
 # GnuPG is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
 # GnuPG is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, see <https://www.gnu.org/licenses/>.
 
 # Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.61)
 min_automake_version="1.14"
 
 # To build a release you need to create a tag with the version number
 # (git tag -s gnupg-2.n.m) and run "./autogen.sh --force".  Please
 # bump the version number immediately *after* the release and do
 # another commit and push so that the git magic is able to work.
 m4_define([mym4_package],[gnupg])
 m4_define([mym4_major], [2])
 m4_define([mym4_minor], [2])
 m4_define([mym4_micro], [5])
 
 # To start a new development series, i.e a new major or minor number
 # you need to mark an arbitrary commit before the first beta release
 # with an annotated tag.  For example the 2.1 branch starts off with
 # the tag "gnupg-2.1-base".  This is used as the base for counting
 # beta numbers before the first release of a series.
 
 # Below is m4 magic to extract and compute the git revision number,
 # the decimalized short revision number, a beta version string and a
 # flag indicating a development version (mym4_isbeta).  Note that the
 # m4 processing is done by autoconf and not during the configure run.
 m4_define([mym4_verslist], m4_split(m4_esyscmd([./autogen.sh --find-version] \
                            mym4_package mym4_major mym4_minor mym4_micro),[:]))
 m4_define([mym4_isbeta],       m4_argn(2, mym4_verslist))
 m4_define([mym4_version],      m4_argn(4, mym4_verslist))
 m4_define([mym4_revision],     m4_argn(7, mym4_verslist))
 m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist))
 m4_esyscmd([echo ]mym4_version[>VERSION])
 AC_INIT([mym4_package],[mym4_version], [https://bugs.gnupg.org])
 
 # When changing the SWDB tag please also adjust the hard coded tags in
 # build-aux/speedo.mk and Makefile.am
 AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg22", [swdb tag for this branch])
 
 NEED_GPG_ERROR_VERSION=1.24
 
 NEED_LIBGCRYPT_API=1
 NEED_LIBGCRYPT_VERSION=1.7.0
 
 NEED_LIBASSUAN_API=2
 NEED_LIBASSUAN_VERSION=2.5.0
 
 NEED_KSBA_API=1
 NEED_KSBA_VERSION=1.3.4
 
 NEED_NTBTLS_API=1
 NEED_NTBTLS_VERSION=0.1.0
 
 NEED_NPTH_API=1
 NEED_NPTH_VERSION=1.2
 
 
 NEED_GNUTLS_VERSION=3.0
 
 NEED_SQLITE_VERSION=3.7
 
 development_version=mym4_isbeta
 PACKAGE=$PACKAGE_NAME
 PACKAGE_GT=${PACKAGE_NAME}2
 VERSION=$PACKAGE_VERSION
 
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_SRCDIR([sm/gpgsm.c])
 AC_CONFIG_HEADER([config.h])
 AM_INIT_AUTOMAKE([serial-tests dist-bzip2 no-dist-gzip])
 AC_CANONICAL_HOST
 AB_INIT
 
 AC_GNU_SOURCE
 
 
 # Some status variables.
 have_gpg_error=no
 have_libgcrypt=no
 have_libassuan=no
 have_ksba=no
 have_ntbtls=no
 have_gnutls=no
 have_sqlite=no
 have_npth=no
 have_libusb=no
 have_system_resolver=no
 gnupg_have_ldap="n/a"
 
 use_zip=yes
 use_bzip2=yes
 use_exec=yes
 use_trust_models=yes
 use_tofu=yes
 use_libdns=yes
 card_support=yes
 use_ccid_driver=auto
 dirmngr_auto_start=yes
 use_tls_library=no
 large_secmem=no
 show_tor_support=no
 
 
 GNUPG_BUILD_PROGRAM(gpg, yes)
 GNUPG_BUILD_PROGRAM(gpgsm, yes)
 # The agent is a required part and can't be disabled anymore.
 build_agent=yes
 GNUPG_BUILD_PROGRAM(scdaemon, yes)
 GNUPG_BUILD_PROGRAM(g13, no)
 GNUPG_BUILD_PROGRAM(dirmngr, yes)
 GNUPG_BUILD_PROGRAM(doc, yes)
 GNUPG_BUILD_PROGRAM(symcryptrun, no)
 # We use gpgtar to unpack test data, hence we always build it.  If the
 # user opts out, we simply don't install it.
 GNUPG_BUILD_PROGRAM(gpgtar, yes)
 GNUPG_BUILD_PROGRAM(wks-tools, no)
 
 AC_SUBST(PACKAGE)
 AC_SUBST(PACKAGE_GT)
 AC_SUBST(VERSION)
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
 AC_DEFINE_UNQUOTED(PACKAGE_GT, "$PACKAGE_GT",
                                 [Name of this package for gettext])
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
 AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT, "$PACKAGE_BUGREPORT",
                                         [Bug report address])
 AC_DEFINE_UNQUOTED(NEED_LIBGCRYPT_VERSION, "$NEED_LIBGCRYPT_VERSION",
                                        [Required version of Libgcrypt])
 AC_DEFINE_UNQUOTED(NEED_KSBA_VERSION, "$NEED_KSBA_VERSION",
                                        [Required version of Libksba])
 AC_DEFINE_UNQUOTED(NEED_NTBTLS_VERSION, "$NEED_NTBTLS_VERSION",
                                        [Required version of NTBTLS])
 
 
 
 # The default is to use the modules from this package and the few
 # other packages in a standard place; i.e where this package gets
 # installed.  With these options it is possible to override these
 # ${prefix} depended values with fixed paths, which can't be replaced
 # at make time.  See also am/cmacros.am and the defaults in AH_BOTTOM.
 AC_ARG_WITH(agent-pgm,
     [  --with-agent-pgm=PATH  Use PATH as the default for the agent)],
           GNUPG_AGENT_PGM="$withval", GNUPG_AGENT_PGM="" )
 AC_SUBST(GNUPG_AGENT_PGM)
 AM_CONDITIONAL(GNUPG_AGENT_PGM, test -n "$GNUPG_AGENT_PGM")
 show_gnupg_agent_pgm="(default)"
 test -n "$GNUPG_AGENT_PGM" && show_gnupg_agent_pgm="$GNUPG_AGENT_PGM"
 
 AC_ARG_WITH(pinentry-pgm,
     [  --with-pinentry-pgm=PATH  Use PATH as the default for the pinentry)],
           GNUPG_PINENTRY_PGM="$withval", GNUPG_PINENTRY_PGM="" )
 AC_SUBST(GNUPG_PINENTRY_PGM)
 AM_CONDITIONAL(GNUPG_PINENTRY_PGM, test -n "$GNUPG_PINENTRY_PGM")
 show_gnupg_pinentry_pgm="(default)"
 test -n "$GNUPG_PINENTRY_PGM" && show_gnupg_pinentry_pgm="$GNUPG_PINENTRY_PGM"
 
 
 AC_ARG_WITH(scdaemon-pgm,
     [  --with-scdaemon-pgm=PATH  Use PATH as the default for the scdaemon)],
           GNUPG_SCDAEMON_PGM="$withval", GNUPG_SCDAEMON_PGM="" )
 AC_SUBST(GNUPG_SCDAEMON_PGM)
 AM_CONDITIONAL(GNUPG_SCDAEMON_PGM, test -n "$GNUPG_SCDAEMON_PGM")
 show_gnupg_scdaemon_pgm="(default)"
 test -n "$GNUPG_SCDAEMON_PGM" && show_gnupg_scdaemon_pgm="$GNUPG_SCDAEMON_PGM"
 
 
 AC_ARG_WITH(dirmngr-pgm,
     [  --with-dirmngr-pgm=PATH  Use PATH as the default for the dirmngr)],
           GNUPG_DIRMNGR_PGM="$withval", GNUPG_DIRMNGR_PGM="" )
 AC_SUBST(GNUPG_DIRMNGR_PGM)
 AM_CONDITIONAL(GNUPG_DIRMNGR_PGM, test -n "$GNUPG_DIRMNGR_PGM")
 show_gnupg_dirmngr_pgm="(default)"
 test -n "$GNUPG_DIRMNGR_PGM" && show_gnupg_dirmngr_pgm="$GNUPG_DIRMNGR_PGM"
 
 AC_ARG_WITH(protect-tool-pgm,
     [  --with-protect-tool-pgm=PATH  Use PATH as the default for the protect-tool)],
           GNUPG_PROTECT_TOOL_PGM="$withval", GNUPG_PROTECT_TOOL_PGM="" )
 AC_SUBST(GNUPG_PROTECT_TOOL_PGM)
 AM_CONDITIONAL(GNUPG_PROTECT_TOOL_PGM, test -n "$GNUPG_PROTECT_TOOL_PGM")
 show_gnupg_protect_tool_pgm="(default)"
 test -n "$GNUPG_PROTECT_TOOL_PGM" \
       && show_gnupg_protect_tool_pgm="$GNUPG_PROTECT_TOOL_PGM"
 
 AC_ARG_WITH(dirmngr-ldap-pgm,
     [  --with-dirmngr-ldap-pgm=PATH  Use PATH as the default for the dirmngr ldap wrapper)],
           GNUPG_DIRMNGR_LDAP_PGM="$withval", GNUPG_DIRMNGR_LDAP_PGM="" )
 AC_SUBST(GNUPG_DIRMNGR_LDAP_PGM)
 AM_CONDITIONAL(GNUPG_DIRMNGR_LDAP_PGM, test -n "$GNUPG_DIRMNGR_LDAP_PGM")
 show_gnupg_dirmngr_ldap_pgm="(default)"
 test -n "$GNUPG_DIRMNGR_LDAP_PGM" \
       && show_gnupg_dirmngr_ldap_pgm="$GNUPG_DIRMNGR_LDAP_PGM"
 
 
 #
 # For a long time gpg 2.x was installed as gpg2.  This changed with
 # 2.2.  This option can be used to install gpg under the name gpg2.
 #
 AC_ARG_ENABLE(gpg-is-gpg2,
     AC_HELP_STRING([--enable-gpg-is-gpg2],[Set installed name of gpg to gpg2]),
     gpg_is_gpg2=$enableval)
 if test "$gpg_is_gpg2" = "yes"; then
    AC_DEFINE(USE_GPG2_HACK, 1, [Define to install gpg as gpg2])
 fi
 AM_CONDITIONAL(USE_GPG2_HACK, test "$gpg_is_gpg2" = "yes")
 
 
 # SELinux support includes tracking of sensitive files to avoid
 # leaking their contents through processing these files by gpg itself
 AC_MSG_CHECKING([whether SELinux support is requested])
 AC_ARG_ENABLE(selinux-support,
               AC_HELP_STRING([--enable-selinux-support],
                              [enable SELinux support]),
               selinux_support=$enableval, selinux_support=no)
 AC_MSG_RESULT($selinux_support)
 
 
 AC_MSG_CHECKING([whether to allocate extra secure memory])
 AC_ARG_ENABLE(large-secmem,
               AC_HELP_STRING([--enable-large-secmem],
                              [allocate extra secure memory]),
               large_secmem=$enableval, large_secmem=no)
 AC_MSG_RESULT($large_secmem)
 if test "$large_secmem" = yes ; then
    SECMEM_BUFFER_SIZE=65536
 else
    SECMEM_BUFFER_SIZE=32768
 fi
 AC_DEFINE_UNQUOTED(SECMEM_BUFFER_SIZE,$SECMEM_BUFFER_SIZE,
                    [Size of secure memory buffer])
 
 AC_MSG_CHECKING([whether to enable trust models])
 AC_ARG_ENABLE(trust-models,
               AC_HELP_STRING([--disable-trust-models],
                              [disable all trust models except "always"]),
               use_trust_models=$enableval)
 AC_MSG_RESULT($use_trust_models)
 if test "$use_trust_models" = no ; then
     AC_DEFINE(NO_TRUST_MODELS, 1,
              [Define to include only trust-model always])
 fi
 
 AC_MSG_CHECKING([whether to enable TOFU])
 AC_ARG_ENABLE(tofu,
                 AC_HELP_STRING([--disable-tofu],
                                [disable the TOFU trust model]),
               use_tofu=$enableval, use_tofu=$use_trust_models)
 AC_MSG_RESULT($use_tofu)
 if test "$use_trust_models" = no && test "$use_tofu" = yes; then
     AC_MSG_ERROR([both --disable-trust-models and --enable-tofu given])
 fi
 
 AC_MSG_CHECKING([whether to enable libdns])
 AC_ARG_ENABLE(libdns,
                 AC_HELP_STRING([--disable-libdns],
                                [do not build with libdns support]),
               use_libdns=$enableval, use_libdns=yes)
 AC_MSG_RESULT($use_libdns)
 if test x"$use_libdns" = xyes ; then
     AC_DEFINE(USE_LIBDNS, 1, [Build with integrated libdns support])
 fi
 AM_CONDITIONAL(USE_LIBDNS, test "$use_libdns" = yes)
 
 
 #
 # Options to disable algorithm
 #
 
 GNUPG_GPG_DISABLE_ALGO([rsa],[RSA public key])
 # Elgamal is a MUST algorithm
 # DSA is a MUST algorithm
 GNUPG_GPG_DISABLE_ALGO([ecdh],[ECDH public key])
 GNUPG_GPG_DISABLE_ALGO([ecdsa],[ECDSA public key])
 GNUPG_GPG_DISABLE_ALGO([eddsa],[EdDSA public key])
 
 GNUPG_GPG_DISABLE_ALGO([idea],[IDEA cipher])
 # 3DES is a MUST algorithm
 GNUPG_GPG_DISABLE_ALGO([cast5],[CAST5 cipher])
 GNUPG_GPG_DISABLE_ALGO([blowfish],[BLOWFISH cipher])
 GNUPG_GPG_DISABLE_ALGO([aes128],[AES128 cipher])
 GNUPG_GPG_DISABLE_ALGO([aes192],[AES192 cipher])
 GNUPG_GPG_DISABLE_ALGO([aes256],[AES256 cipher])
 GNUPG_GPG_DISABLE_ALGO([twofish],[TWOFISH cipher])
 GNUPG_GPG_DISABLE_ALGO([camellia128],[CAMELLIA128 cipher])
 GNUPG_GPG_DISABLE_ALGO([camellia192],[CAMELLIA192 cipher])
 GNUPG_GPG_DISABLE_ALGO([camellia256],[CAMELLIA256 cipher])
 
 GNUPG_GPG_DISABLE_ALGO([md5],[MD5 hash])
 # SHA1 is a MUST algorithm
 GNUPG_GPG_DISABLE_ALGO([rmd160],[RIPE-MD160 hash])
 GNUPG_GPG_DISABLE_ALGO([sha224],[SHA-224 hash])
 # SHA256 is a MUST algorithm for GnuPG.
 GNUPG_GPG_DISABLE_ALGO([sha384],[SHA-384 hash])
 GNUPG_GPG_DISABLE_ALGO([sha512],[SHA-512 hash])
 
 
 # Allow disabling of zip support.
 # This is in general not a good idea because according to rfc4880 OpenPGP
 # implementations SHOULD support ZLIB.
 AC_MSG_CHECKING([whether to enable the ZIP and ZLIB compression algorithm])
 AC_ARG_ENABLE(zip,
    AC_HELP_STRING([--disable-zip],
                   [disable the ZIP and ZLIB compression algorithm]),
    use_zip=$enableval)
 AC_MSG_RESULT($use_zip)
 
 # Allow disabling of bzib2 support.
 # It is defined only after we confirm the library is available later
 AC_MSG_CHECKING([whether to enable the BZIP2 compression algorithm])
 AC_ARG_ENABLE(bzip2,
    AC_HELP_STRING([--disable-bzip2],[disable the BZIP2 compression algorithm]),
    use_bzip2=$enableval)
 AC_MSG_RESULT($use_bzip2)
 
 # Configure option to allow or disallow execution of external
 # programs, like a photo viewer.
 AC_MSG_CHECKING([whether to enable external program execution])
 AC_ARG_ENABLE(exec,
     AC_HELP_STRING([--disable-exec],[disable all external program execution]),
     use_exec=$enableval)
 AC_MSG_RESULT($use_exec)
 if test "$use_exec" = no ; then
     AC_DEFINE(NO_EXEC,1,[Define to disable all external program execution])
 fi
 
 if test "$use_exec" = yes ; then
   AC_MSG_CHECKING([whether to enable photo ID viewing])
   AC_ARG_ENABLE(photo-viewers,
       [  --disable-photo-viewers disable photo ID viewers],
       [if test "$enableval" = no ; then
          AC_DEFINE(DISABLE_PHOTO_VIEWER,1,[define to disable photo viewing])
       fi],enableval=yes)
   gnupg_cv_enable_photo_viewers=$enableval
   AC_MSG_RESULT($enableval)
 
   if test "$gnupg_cv_enable_photo_viewers" = yes ; then
     AC_MSG_CHECKING([whether to use a fixed photo ID viewer])
     AC_ARG_WITH(photo-viewer,
         [  --with-photo-viewer=FIXED_VIEWER  set a fixed photo ID viewer],
         [if test "$withval" = yes ; then
            withval=no
         elif test "$withval" != no ; then
            AC_DEFINE_UNQUOTED(FIXED_PHOTO_VIEWER,"$withval",
   	                    [if set, restrict photo-viewer to this])
         fi],withval=no)
     AC_MSG_RESULT($withval)
   fi
 fi
 
 
 #
 # Check for the key/uid cache size.  This can't be zero, but can be
 # pretty small on embedded systems.  This is used for the gpg part.
 #
 AC_MSG_CHECKING([for the size of the key and uid cache])
 AC_ARG_ENABLE(key-cache,
         AC_HELP_STRING([--enable-key-cache=SIZE],
                        [Set key cache to SIZE (default 4096)]),,enableval=4096)
 if test "$enableval" = "no"; then
    enableval=5
 elif test "$enableval" = "yes" || test "$enableval" = ""; then
    enableval=4096
 fi
 changequote(,)dnl
 key_cache_size=`echo "$enableval" | sed 's/[A-Za-z]//g'`
 changequote([,])dnl
 if test "$enableval" != "$key_cache_size" || test "$key_cache_size" -lt 5; then
    AC_MSG_ERROR([invalid key-cache size])
 fi
 AC_MSG_RESULT($key_cache_size)
 AC_DEFINE_UNQUOTED(PK_UID_CACHE_SIZE,$key_cache_size,
                   [Size of the key and UID caches])
 
 
 
 #
 # Check whether we want to use Linux capabilities
 #
 AC_MSG_CHECKING([whether use of capabilities is requested])
 AC_ARG_WITH(capabilities,
     [  --with-capabilities     use linux capabilities [default=no]],
 [use_capabilities="$withval"],[use_capabilities=no])
 AC_MSG_RESULT($use_capabilities)
 
 #
 # Check whether to disable the card support
 AC_MSG_CHECKING([whether smartcard support is requested])
 AC_ARG_ENABLE(card-support,
               AC_HELP_STRING([--disable-card-support],
                              [disable smartcard support]),
               card_support=$enableval)
 AC_MSG_RESULT($card_support)
 if test "$card_support" = yes ; then
   AC_DEFINE(ENABLE_CARD_SUPPORT,1,[Define to include smartcard support])
 else
   build_scdaemon=no
 fi
 
 #
 # Allow disabling of internal CCID support.
 # It is defined only after we confirm the library is available later
 #
 AC_MSG_CHECKING([whether to enable the internal CCID driver])
 AC_ARG_ENABLE(ccid-driver,
               AC_HELP_STRING([--disable-ccid-driver],
                              [disable the internal CCID driver]),
               use_ccid_driver=$enableval)
 AC_MSG_RESULT($use_ccid_driver)
 
 AC_MSG_CHECKING([whether to auto start dirmngr])
 AC_ARG_ENABLE(dirmngr-auto-start,
               AC_HELP_STRING([--disable-dirmngr-auto-start],
                              [disable auto starting of the dirmngr]),
               dirmngr_auto_start=$enableval)
 AC_MSG_RESULT($dirmngr_auto_start)
 if test "$dirmngr_auto_start" = yes ; then
     AC_DEFINE(USE_DIRMNGR_AUTO_START,1,
               [Define to enable auto starting of the dirmngr])
 fi
 
 
 #
 # To avoid double inclusion of config.h which might happen at some
 # places, we add the usual double inclusion protection at the top of
 # config.h.
 #
 AH_TOP([
 #ifndef GNUPG_CONFIG_H_INCLUDED
 #define GNUPG_CONFIG_H_INCLUDED
 ])
 
 #
 # Stuff which goes at the bottom of config.h.
 #
 AH_BOTTOM([
 /* This is the major version number of GnuPG so that
    source included files can test for this.  Note, that
    we use 2 here even for GnuPG 1.9.x. */
 #define GNUPG_MAJOR_VERSION 2
 
 /* Now to separate file name parts.
    Please note that the string version must not contain more
    than one character because the code assumes strlen()==1 */
 #ifdef HAVE_DOSISH_SYSTEM
 #define DIRSEP_C '\\'
 #define DIRSEP_S "\\"
 #define EXTSEP_C '.'
 #define EXTSEP_S "."
 #define PATHSEP_C ';'
 #define PATHSEP_S ";"
 #define EXEEXT_S ".exe"
 #else
 #define DIRSEP_C '/'
 #define DIRSEP_S "/"
 #define EXTSEP_C '.'
 #define EXTSEP_S "."
 #define PATHSEP_C ':'
 #define PATHSEP_S ":"
 #define EXEEXT_S ""
 #endif
 
 /* This is the same as VERSION, but should be overridden if the
    platform cannot handle things like dots '.' in filenames. Set
    SAFE_VERSION_DOT and SAFE_VERSION_DASH to whatever SAFE_VERSION
    uses for dots and dashes. */
 #define SAFE_VERSION VERSION
 #define SAFE_VERSION_DOT  '.'
 #define SAFE_VERSION_DASH '-'
 
 /* Some global constants.
  * Note that the homedir must not end in a slash.  */
 #ifdef HAVE_DOSISH_SYSTEM
 # ifdef HAVE_DRIVE_LETTERS
 #  define GNUPG_DEFAULT_HOMEDIR "c:/gnupg"
 # else
 #  define GNUPG_DEFAULT_HOMEDIR "/gnupg"
 # endif
 #elif defined(__VMS)
 #define GNUPG_DEFAULT_HOMEDIR "/SYS$LOGIN/gnupg"
 #else
 #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg"
 #endif
 #define GNUPG_PRIVATE_KEYS_DIR  "private-keys-v1.d"
 #define GNUPG_OPENPGP_REVOC_DIR "openpgp-revocs.d"
 
 /* For some systems (DOS currently), we hardcode the path here.  For
    POSIX systems the values are constructed by the Makefiles, so that
    the values may be overridden by the make invocations; this is to
    comply with the GNU coding standards.  Note that these values are
    only defaults.  */
 #ifdef HAVE_DOSISH_SYSTEM
 # ifdef HAVE_DRIVE_LETTERS
 #  define GNUPG_BINDIR      "c:\\gnupg"
 #  define GNUPG_LIBEXECDIR  "c:\\gnupg"
 #  define GNUPG_LIBDIR      "c:\\gnupg"
 #  define GNUPG_DATADIR     "c:\\gnupg"
 #  define GNUPG_SYSCONFDIR  "c:\\gnupg"
 # else
 #  define GNUPG_BINDIR      "\\gnupg"
 #  define GNUPG_LIBEXECDIR  "\\gnupg"
 #  define GNUPG_LIBDIR      "\\gnupg"
 #  define GNUPG_DATADIR     "\\gnupg"
 #  define GNUPG_SYSCONFDIR  "\\gnupg"
 # endif
 #endif
 
 /* Derive some other constants. */
 #if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID))
 #define EXEC_TEMPFILE_ONLY
 #endif
 
 
 /* We didn't define endianness above, so get it from OS macros.  This
    is intended for making fat binary builds on OS X. */
 #if !defined(BIG_ENDIAN_HOST) && !defined(LITTLE_ENDIAN_HOST)
 #if defined(__BIG_ENDIAN__)
 #define BIG_ENDIAN_HOST 1
 #elif defined(__LITTLE_ENDIAN__)
 #define LITTLE_ENDIAN_HOST 1
 #else
 #error "No endianness found"
 #endif
 #endif
 
 
 /* Hack used for W32: ldap.m4 also tests for the ASCII version of
    ldap_start_tls_s because that is the actual symbol used in the
    library.  winldap.h redefines it to our commonly used value,
    thus we define our usual macro here.  */
 #ifdef HAVE_LDAP_START_TLS_SA
 # ifndef HAVE_LDAP_START_TLS_S
 #  define HAVE_LDAP_START_TLS_S 1
 # endif
 #endif
 
 /* Provide the es_ macro for estream.  */
 #define GPGRT_ENABLE_ES_MACROS 1
 
 /* Tell libgcrypt not to use its own libgpg-error implementation. */
 #define USE_LIBGPG_ERROR 1
 
 /* Tell Libgcrypt not to include deprecated definitions.  */
 #define GCRYPT_NO_DEPRECATED 1
 
 /* Our HTTP code is used in estream mode.  */
 #define HTTP_USE_ESTREAM 1
 
 /* Under W32 we do an explicit socket initialization, thus we need to
    avoid the on-demand initialization which would also install an atexit
    handler.  */
 #define HTTP_NO_WSASTARTUP
 
 /* Under Windows we use the gettext code from libgpg-error.  */
 #define GPG_ERR_ENABLE_GETTEXT_MACROS
 
 /* Under WindowsCE we use the strerror replacement from libgpg-error.  */
 #define GPG_ERR_ENABLE_ERRNO_MACROS
 
 #endif /*GNUPG_CONFIG_H_INCLUDED*/
 ])
 
 
 AM_MAINTAINER_MODE
 AC_ARG_VAR(SYSROOT,[locate config scripts also below that directory])
 
 # Checks for programs.
 AC_MSG_NOTICE([checking for programs])
 AC_PROG_MAKE_SET
 AM_SANITY_CHECK
 missing_dir=`cd $ac_aux_dir && pwd`
 AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
 AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
 AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
 AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
 AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
 AM_SILENT_RULES
 AC_PROG_AWK
 AC_PROG_CC
 AC_PROG_CPP
 AM_PROG_CC_C_O
 if test "x$ac_cv_prog_cc_c89" = "xno" ; then
   AC_MSG_ERROR([[No C-89 compiler found]])
 fi
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_RANLIB
 AC_CHECK_TOOL(AR, ar, :)
 AC_PATH_PROG(PERL,"perl")
 AC_CHECK_TOOL(WINDRES, windres, :)
 AC_PATH_PROG(YAT2M, "yat2m")
 AC_ARG_VAR(YAT2M, [tool to convert texi to man pages])
 AM_CONDITIONAL(HAVE_YAT2M, test -n "$ac_cv_path_YAT2M")
 AC_ISC_POSIX
 AC_SYS_LARGEFILE
 GNUPG_CHECK_USTAR
 
 
 # We need to compile and run a program on the build machine.  A
 # comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in
 # the AC archive is broken for autoconf 2.57.  Given that there is no
 # newer version of that macro, we assume that it is also broken for
 # autoconf 2.61 and thus we use a simple but usually sufficient
 # approach.
 AC_MSG_CHECKING(for cc for build)
 if test "$cross_compiling" = "yes"; then
   CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
 else
   CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
 fi
 AC_MSG_RESULT($CC_FOR_BUILD)
 AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler])
 
 # We need to call this macro because other pkg-config macros are
 # not always used.
 PKG_PROG_PKG_CONFIG
 
 
 try_gettext=yes
 require_iconv=yes
 have_dosish_system=no
 have_w32_system=no
 have_w32ce_system=no
 have_android_system=no
 use_simple_gettext=no
 use_ldapwrapper=yes
 mmap_needed=yes
 case "${host}" in
     *-mingw32*)
         # special stuff for Windoze NT
         ac_cv_have_dev_random=no
         AC_DEFINE(USE_ONLY_8DOT3,1,
                   [Set this to limit filenames to the 8.3 format])
         AC_DEFINE(USE_SIMPLE_GETTEXT,1,
                   [Because the Unix gettext has too much overhead on
                    MingW32 systems and these systems lack Posix functions,
                    we use a simplified version of gettext])
         have_dosish_system=yes
         have_w32_system=yes
         require_iconv=no
         use_ldapwrapper=no  # Fixme: Do this only for CE.
         case "${host}" in
           *-mingw32ce*)
             have_w32ce_system=yes
             ;;
           *)
             AC_DEFINE(HAVE_DRIVE_LETTERS,1,
                       [Defined if the OS supports drive letters.])
             ;;
         esac
         try_gettext="no"
 	use_simple_gettext=yes
 	mmap_needed=no
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         # OS/2 with the EMX environment
         ac_cv_have_dev_random=no
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         have_dosish_system=yes
         try_gettext="no"
         ;;
 
     i?86-*-msdosdjgpp*)
         # DOS with the DJGPP environment
         ac_cv_have_dev_random=no
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         have_dosish_system=yes
         try_gettext="no"
         ;;
 
     *-*-hpux*)
         if test -z "$GCC" ; then
             CFLAGS="-Ae -D_HPUX_SOURCE $CFLAGS"
         fi
         ;;
     *-dec-osf4*)
         if test -z "$GCC" ; then
             # Suppress all warnings
             # to get rid of the unsigned/signed char mismatch warnings.
             CFLAGS="-w $CFLAGS"
         fi
         ;;
     *-dec-osf5*)
         if test -z "$GCC" ; then
             # Use the newer compiler `-msg_disable ptrmismatch1' to
             # get rid of the unsigned/signed char mismatch warnings.
             # Using this may hide other pointer mismatch warnings, but
 	    # it at least lets other warning classes through
             CFLAGS="-msg_disable ptrmismatch1 $CFLAGS"
         fi
         ;;
     m68k-atari-mint)
         ;;
     *-linux-android*)
         have_android_system=yes
         # Android is fully utf-8 and we do not want to use iconv to
         # keeps things simple
         require_iconv=no
         ;;
     *-apple-darwin*)
         AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
                   Expose all libc features (__DARWIN_C_FULL).)
         ;;
     *)
        ;;
 esac
 
 if test "$have_dosish_system" = yes; then
    AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
              [Defined if we run on some of the PCDOS like systems
               (DOS, Windoze. OS/2) with special properties like
               no file modes, case insensitive file names and preferred
               use of backslashes as directory name separators.])
 fi
 AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes)
 
 AM_CONDITIONAL(USE_SIMPLE_GETTEXT, test x"$use_simple_gettext" = xyes)
 
 if test "$have_w32_system" = yes; then
    AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system])
    if test "$have_w32ce_system" = yes; then
       AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE])
    fi
 fi
 AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
 AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
 
 if test "$have_android_system" = yes; then
    AC_DEFINE(HAVE_ANDROID_SYSTEM,1, [Defined if we build for an Android system])
 fi
 AM_CONDITIONAL(HAVE_ANDROID_SYSTEM, test "$have_android_system" = yes)
 
 
 # (These need to go after AC_PROG_CC so that $EXEEXT is defined)
 AC_DEFINE_UNQUOTED(EXEEXT,"$EXEEXT",[The executable file extension, if any])
 
 
 #
 # Checks for libraries.
 #
 AC_MSG_NOTICE([checking for libraries])
 
 
 #
 # libgpg-error is a library with error codes shared between GnuPG
 # related projects.
 #
 AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
                   have_gpg_error=yes,have_gpg_error=no)
 
 
 #
 # Libgcrypt is our generic crypto library
 #
 AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
         have_libgcrypt=yes,have_libgcrypt=no)
 
 
 #
 # libassuan is used for IPC
 #
 AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION",
                   have_libassuan=yes,have_libassuan=no)
 if test "$have_libassuan" = "yes"; then
   AC_DEFINE_UNQUOTED(GNUPG_LIBASSUAN_VERSION, "$libassuan_version",
                      [version of the libassuan library])
   show_tor_support="only .onion"
 fi
 
 
 #
 # libksba is our X.509 support library
 #
 AM_PATH_KSBA("$NEED_KSBA_API:$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no)
 
 
 #
 # libusb allows us to use the integrated CCID smartcard reader driver.
 #
 # FiXME: Use GNUPG_CHECK_LIBUSB and modify to use separate AC_SUBSTs.
 if test "$use_ccid_driver" = auto || test "$use_ccid_driver" = yes; then
    case "${host}" in
      *-mingw32*)
        LIBUSB_NAME=
        LIBUSB_LIBS=
        LIBUSB_CPPFLAGS=
        ;;
      *-*-darwin*)
        LIBUSB_NAME=usb-1.0
        LIBUSB_LIBS="-Wl,-framework,CoreFoundation -Wl,-framework,IOKit"
        ;;
      *-*-freebsd*)
        # FreeBSD has a native 1.0 compatible library by -lusb.
        LIBUSB_NAME=usb
        LIBUSB_LIBS=
        ;;
      *)
        LIBUSB_NAME=usb-1.0
        LIBUSB_LIBS=
        ;;
    esac
 fi
 if test x"$LIBUSB_NAME" != x ; then
    AC_CHECK_LIB($LIBUSB_NAME, libusb_init,
                 [ LIBUSB_LIBS="-l$LIBUSB_NAME $LIBUSB_LIBS"
                   have_libusb=yes ])
    AC_MSG_CHECKING([libusb include dir])
    usb_incdir_found="no"
    for _incdir in "" "/usr/include/libusb-1.0" "/usr/local/include/libusb-1.0"; do
      _libusb_save_cppflags=$CPPFLAGS
      if test -n "${_incdir}"; then
        CPPFLAGS="-I${_incdir} ${CPPFLAGS}"
      fi
      AC_PREPROC_IFELSE([AC_LANG_SOURCE([[@%:@include <libusb.h>]])],
      [usb_incdir=${_incdir}; usb_incdir_found="yes"], [])
      CPPFLAGS=${_libusb_save_cppflags}
      if test "$usb_incdir_found" = "yes"; then
        break
      fi
    done
    if test "$usb_incdir_found" = "yes"; then
      AC_MSG_RESULT([${usb_incdir}])
    else
      AC_MSG_RESULT([not found])
      usb_incdir=""
      have_libusb=no
      if test "$use_ccid_driver" != yes; then
        use_ccid_driver=no
      fi
      LIBUSB_LIBS=""
    fi
 
    if test "$have_libusb" = yes; then
      AC_DEFINE(HAVE_LIBUSB,1, [defined if libusb is available])
    fi
    if test x"$usb_incdir" = x; then
      LIBUSB_CPPFLAGS=""
    else
      LIBUSB_CPPFLAGS="-I${usb_incdir}"
    fi
 fi
 AC_SUBST(LIBUSB_LIBS)
 AC_SUBST(LIBUSB_CPPFLAGS)
 
 #
 # Check whether it is necessary to link against libdl.
 # (For example to load libpcsclite)
 #
 gnupg_dlopen_save_libs="$LIBS"
 LIBS=""
 AC_SEARCH_LIBS(dlopen, c dl,,,)
 DL_LIBS=$LIBS
 AC_SUBST(DL_LIBS)
 LIBS="$gnupg_dlopen_save_libs"
 
 
 # Checks for g10
 
 AC_ARG_ENABLE(sqlite,
                 AC_HELP_STRING([--disable-sqlite],
                                [disable the use of SQLITE]),
               try_sqlite=$enableval, try_sqlite=yes)
 
 if test x"$use_tofu" = xyes ; then
   if test x"$try_sqlite" = xyes ; then
     PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= $NEED_SQLITE_VERSION],
                                  [have_sqlite=yes],
                                  [have_sqlite=no])
   fi
   if test "$have_sqlite" = "yes"; then
     :
     AC_SUBST([SQLITE3_CFLAGS])
     AC_SUBST([SQLITE3_LIBS])
   else
     use_tofu=no
     tmp=$(echo "$SQLITE3_PKG_ERRORS" | tr '\n' '\v' | sed 's/\v/\n*** /g')
     AC_MSG_WARN([[
 ***
 *** Building without SQLite support - TOFU disabled
 ***
 *** $tmp]])
   fi
 fi
 
 AM_CONDITIONAL(SQLITE3, test "$have_sqlite" = "yes")
 
 if test x"$use_tofu" = xyes ; then
     AC_DEFINE(USE_TOFU, 1, [Enable to build the TOFU code])
 fi
 
 
 # Checks for g13
 
 AC_PATH_PROG(ENCFS, encfs, /usr/bin/encfs)
 AC_DEFINE_UNQUOTED(ENCFS,
 	"${ENCFS}", [defines the filename of the encfs program])
 
 AC_PATH_PROG(FUSERMOUNT, fusermount, /usr/bin/fusermount)
 AC_DEFINE_UNQUOTED(FUSERMOUNT,
 	"${FUSERMOUNT}", [defines the filename of the fusermount program])
 
 
 # Checks for dirmngr
 
 
 #
 # Checks for symcryptrun:
 #
 
 # libutil has openpty() and login_tty().
 AC_CHECK_LIB(util, openpty,
               [ LIBUTIL_LIBS="$LIBUTIL_LIBS -lutil"
                 AC_DEFINE(HAVE_LIBUTIL,1,
                          [defined if libutil is available])
              ])
 AC_SUBST(LIBUTIL_LIBS)
 
 # shred is used to clean temporary plain text files.
 AC_PATH_PROG(SHRED, shred, /usr/bin/shred)
 AC_DEFINE_UNQUOTED(SHRED,
 	"${SHRED}", [defines the filename of the shred program])
 
 
 #
 # Check whether the nPth library is available
 #
 AM_PATH_NPTH("$NEED_NPTH_API:$NEED_NPTH_VERSION",have_npth=yes,have_npth=no)
 if test "$have_npth" = "yes"; then
   AC_DEFINE(HAVE_NPTH, 1,
               [Defined if the New Portable Thread Library is available])
   AC_DEFINE(USE_NPTH, 1,
               [Defined if support for nPth is requested and nPth is available])
 else
   AC_MSG_WARN([[
 ***
 *** To support concurrent access for example in gpg-agent and the SCdaemon
 *** we need the support of the New Portable Threads Library.
 ***]])
 fi
 
 
 #
 # NTBTLS is our TLS library.  If it is not available fallback to
 # GNUTLS.
 #
 AC_ARG_ENABLE(ntbtls,
               AC_HELP_STRING([--disable-ntbtls],
                              [disable the use of NTBTLS as TLS library]),
               try_ntbtls=$enableval, try_ntbtls=yes)
 if test x"$try_ntbtls" = xyes ; then
   AM_PATH_NTBTLS("$NEED_NTBTLS_API:$NEED_NTBTLS_VERSION",
                  [have_ntbtls=yes],[have_ntbtls=no])
 fi
 if test "$have_ntbtls" = yes ; then
    use_tls_library=ntbtls
    AC_DEFINE(HTTP_USE_NTBTLS, 1, [Enable NTBTLS support in http.c])
 else
   AC_ARG_ENABLE(gnutls,
                 AC_HELP_STRING([--disable-gnutls],
                                [disable GNUTLS as fallback TLS library]),
                 try_gnutls=$enableval, try_gnutls=yes)
   if test x"$try_gnutls" = xyes ; then
     PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= $NEED_GNUTLS_VERSION],
                                    [have_gnutls=yes],
                                    [have_gnutls=no])
   fi
   if test "$have_gnutls" = "yes"; then
     AC_SUBST([LIBGNUTLS_CFLAGS])
     AC_SUBST([LIBGNUTLS_LIBS])
     use_tls_library=gnutls
     AC_DEFINE(HTTP_USE_GNUTLS, 1, [Enable GNUTLS support in http.c])
   else
     tmp=$(echo "$LIBGNUTLS_PKG_ERRORS" | tr '\n' '\v' | sed 's/\v/\n*** /g')
     AC_MSG_WARN([[
 ***
 *** Building without NTBTLS and GNUTLS - no TLS access to keyservers.
 ***
 *** $tmp]])
   fi
 fi
 
 #
 # Allow to set a fixed trust store file for system provided certificates.
 #
 AC_ARG_WITH([default-trust-store-file],
             [AC_HELP_STRING([--with-default-trust-store-file=FILE],
                             [Use FILE as system trust store])],
             default_trust_store_file="$withval",
             default_trust_store_file="")
 if test x"$default_trust_store_file" = xno;then
   default_trust_store_file=""
 fi
 if test x"$default_trust_store_file" != x ; then
   AC_DEFINE_UNQUOTED([DEFAULT_TRUST_STORE_FILE],
     ["$default_trust_store_file"], [Use as default system trust store file])
 fi
 
 
 AC_MSG_NOTICE([checking for networking options])
 
 #
 # Must check for network library requirements before doing link tests
 # for ldap, for example. If ldap libs are static (or dynamic and without
 # ELF runtime link paths), then link will fail and LDAP support won't
 # be detected.
 #
 AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname,
 	[NETLIBS="-lnsl $NETLIBS"]))
 AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
 	[NETLIBS="-lsocket $NETLIBS"]))
 
 
 #
 # Check standard resolver functions.
 #
 if test "$build_dirmngr" = "yes"; then
   _dns_save_libs=$LIBS
   LIBS=""
 
   # Find the system resolver which can always be enabled with
   # the dirmngr option --standard-resolver.
 
   # the double underscore thing is a glibc-ism?
   AC_SEARCH_LIBS(res_query,resolv bind,,
                  AC_SEARCH_LIBS(__res_query,resolv bind,,have_resolver=no))
   AC_SEARCH_LIBS(dn_expand,resolv bind,,
                  AC_SEARCH_LIBS(__dn_expand,resolv bind,,have_resolver=no))
 
   # macOS renames dn_skipname into res_9_dn_skipname in <resolv.h>,
   # and for some reason fools us into believing we don't need
   # -lresolv even if we do.  Since the test program checking for the
   # symbol does not include <resolv.h>, we need to check for the
   # renamed symbol explicitly.
   AC_SEARCH_LIBS(res_9_dn_skipname,resolv bind,,
       AC_SEARCH_LIBS(dn_skipname,resolv bind,,
           AC_SEARCH_LIBS(__dn_skipname,resolv bind,,have_resolver=no)))
 
   if test x"$have_resolver" != xno ; then
 
       # Make sure that the BIND 4 resolver interface is workable before
       # enabling any code that calls it.  At some point I'll rewrite the
       # code to use the BIND 8 resolver API.
       # We might also want to use libdns instead.
 
     AC_MSG_CHECKING([whether the resolver is usable])
     AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <resolv.h>]],
 [[unsigned char answer[PACKETSZ];
   res_query("foo.bar",C_IN,T_A,answer,PACKETSZ);
   dn_skipname(0,0);
   dn_expand(0,0,0,0,0);
 ]])],have_resolver=yes,have_resolver=no)
     AC_MSG_RESULT($have_resolver)
 
     # This is Apple-specific and somewhat bizarre as they changed the
     # define in bind 8 for some reason.
 
     if test x"$have_resolver" != xyes ; then
       AC_MSG_CHECKING(
            [whether I can make the resolver usable with BIND_8_COMPAT])
       AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define BIND_8_COMPAT
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <resolv.h>]],
 [[unsigned char answer[PACKETSZ];
   res_query("foo.bar",C_IN,T_A,answer,PACKETSZ);
   dn_skipname(0,0); dn_expand(0,0,0,0,0);
 ]])],[have_resolver=yes ; need_compat=yes])
       AC_MSG_RESULT($have_resolver)
     fi
   fi
 
   if test x"$have_resolver" = xyes ; then
     AC_DEFINE(HAVE_SYSTEM_RESOLVER,1,[The system's resolver is usable.])
     DNSLIBS="$DNSLIBS $LIBS"
     if test x"$need_compat" = xyes ; then
       AC_DEFINE(BIND_8_COMPAT,1,[an Apple OSXism])
     fi
     if test "$use_libdns" = yes; then
      show_tor_support=yes
     fi
   elif test "$use_libdns" = yes; then
     show_tor_support=yes
   else
     AC_MSG_WARN([[
 ***
 *** The system's DNS resolver is not usable.
 *** Dirmngr functionality is limited.
 ***]])
     show_tor_support="${show_tor_support} (no system resolver)"
   fi
 
   if test "$have_w32_system" = yes; then
     if test "$use_libdns" = yes; then
       DNSLIBS="$DNSLIBS -liphlpapi"
     fi
   fi
 
   LIBS=$_dns_save_libs
 fi
 
 AC_SUBST(DNSLIBS)
 
 
 #
 # Check for LDAP
 #
 # Note that running the check changes the variable
 # gnupg_have_ldap from "n/a" to "no" or "yes".
 
 AC_ARG_ENABLE(ldap,
     AC_HELP_STRING([--disable-ldap],[disable LDAP support]),
     [if test "$enableval" = "no"; then gnupg_have_ldap=no; fi])
 
 if test "$gnupg_have_ldap" != "no" ; then
   if test "$build_dirmngr" = "yes" ; then
      GNUPG_CHECK_LDAP($NETLIBS)
      AC_CHECK_LIB(lber, ber_free,
                   [ LBER_LIBS="$LBER_LIBS -llber"
                     AC_DEFINE(HAVE_LBER,1,
                              [defined if liblber is available])
                     have_lber=yes
                  ])
   fi
 fi
 AC_SUBST(LBER_LIBS)
 if test "$gnupg_have_ldap" = "no"; then
     AC_MSG_WARN([[
 ***
 *** Building without LDAP support.
 *** No CRL access or X.509 certificate search available.
 ***]])
 fi
 
 AM_CONDITIONAL(USE_LDAP, [test "$gnupg_have_ldap" = yes])
 if test "$gnupg_have_ldap" = yes ; then
   AC_DEFINE(USE_LDAP,1,[Defined if LDAP is support])
 else
  use_ldapwrapper=no
 fi
 
 if test "$use_ldapwrapper" = yes; then
    AC_DEFINE(USE_LDAPWRAPPER,1, [Build dirmngr with LDAP wrapper process])
 fi
 AM_CONDITIONAL(USE_LDAPWRAPPER, test "$use_ldapwrapper" = yes)
 
 
 
 
 #
 # Check for sendmail
 #
 # This isn't necessarily sendmail itself, but anything that gives a
 # sendmail-ish interface to the outside world.  That includes Exim,
 # Postfix, etc.  Basically, anything that can handle "sendmail -t".
 AC_ARG_WITH(mailprog,
       AC_HELP_STRING([--with-mailprog=NAME],
                      [use "NAME -t" for mail transport]),
              ,with_mailprog=yes)
 if test x"$with_mailprog" = xyes ; then
     AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib)
 elif test x"$with_mailprog" != xno ; then
     AC_MSG_CHECKING([for a mail transport program])
     AC_SUBST(SENDMAIL,$with_mailprog)
     AC_MSG_RESULT($with_mailprog)
 fi
 
 
 #
 # Construct a printable name of the OS
 #
 case "${host}" in
     *-mingw32ce*)
         PRINTABLE_OS_NAME="W32CE"
         ;;
     *-mingw32*)
         PRINTABLE_OS_NAME="MingW32"
         ;;
     *-*-cygwin*)
         PRINTABLE_OS_NAME="Cygwin"
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         PRINTABLE_OS_NAME="OS/2"
         ;;
     i?86-*-msdosdjgpp*)
         PRINTABLE_OS_NAME="MSDOS/DJGPP"
         try_dynload=no
         ;;
     *-linux*)
         PRINTABLE_OS_NAME="GNU/Linux"
         ;;
     *)
         PRINTABLE_OS_NAME=`uname -s || echo "Unknown"`
         ;;
 esac
 AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME",
                    [A human readable text with the name of the OS])
 
 
 #
 # Checking for iconv
 #
 if test "$require_iconv" = yes; then
   AM_ICONV
 else
   LIBICONV=
   LTLIBICONV=
   AC_SUBST(LIBICONV)
   AC_SUBST(LTLIBICONV)
 fi
 
 
 #
 # Check for gettext
 #
 # This is "GNU gnupg" - The project-id script from gettext
 #                       needs this string
 #
 AC_MSG_NOTICE([checking for gettext])
 AM_PO_SUBDIRS
 AM_GNU_GETTEXT_VERSION([0.17])
 if test "$try_gettext" = yes; then
   AM_GNU_GETTEXT([external],[need-ngettext])
 
   # gettext requires some extra checks.  These really should be part of
   # the basic AM_GNU_GETTEXT macro.  TODO: move other gettext-specific
   # function checks to here.
 
   AC_CHECK_FUNCS(strchr)
 else
   USE_NLS=no
   USE_INCLUDED_LIBINTL=no
   BUILD_INCLUDED_LIBINTL=no
   POSUB=po
   AC_SUBST(USE_NLS)
   AC_SUBST(USE_INCLUDED_LIBINTL)
   AC_SUBST(BUILD_INCLUDED_LIBINTL)
   AC_SUBST(POSUB)
 fi
 
 # We use HAVE_LANGINFO_CODESET in a couple of places.
 AM_LANGINFO_CODESET
 
 # Checks required for our use of locales
 gt_LC_MESSAGES
 
 
 #
 # SELinux support
 #
 if test "$selinux_support" = yes ; then
   AC_DEFINE(ENABLE_SELINUX_HACKS,1,[Define to enable SELinux support])
 fi
 
 
 #
 # Checks for header files.
 #
 AC_MSG_NOTICE([checking for header files])
 AC_HEADER_STDC
 AC_CHECK_HEADERS([string.h unistd.h langinfo.h termio.h locale.h getopt.h \
                   pty.h utmp.h pwd.h inttypes.h signal.h sys/select.h     \
                   stdint.h signal.h util.h libutil.h termios.h \
-                  sys/ucred.h sys/sysmacros.h sys/mkdev.h])
+                  ucred.h sys/ucred.h sys/sysmacros.h sys/mkdev.h])
 
 AC_HEADER_TIME
 
 
 #
 # Checks for typedefs, structures, and compiler characteristics.
 #
 AC_MSG_NOTICE([checking for system characteristics])
 AC_C_CONST
 AC_C_INLINE
 AC_C_VOLATILE
 AC_TYPE_SIZE_T
 AC_TYPE_MODE_T
 AC_TYPE_SIGNAL
 AC_DECL_SYS_SIGLIST
 
 gl_HEADER_SYS_SOCKET
 gl_TYPE_SOCKLEN_T
 
 AC_SEARCH_LIBS([inet_addr], [nsl])
 
 AC_ARG_ENABLE(endian-check,
               AC_HELP_STRING([--disable-endian-check],
 	      [disable the endian check and trust the OS provided macros]),
 	      endiancheck=$enableval,endiancheck=yes)
 
 if test x"$endiancheck" = xyes ; then
   GNUPG_CHECK_ENDIAN
 fi
 
 # fixme: we should get rid of the byte type
 GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF)
 
 AC_CHECK_SIZEOF(unsigned short)
 AC_CHECK_SIZEOF(unsigned int)
 AC_CHECK_SIZEOF(unsigned long)
 AC_CHECK_SIZEOF(unsigned long long)
 AC_HEADER_TIME
 AC_CHECK_SIZEOF(time_t,,[[
 #include <stdio.h>
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
 #else
 # if HAVE_SYS_TIME_H
 #  include <sys/time.h>
 # else
 #  include <time.h>
 # endif
 #endif
 ]])
 GNUPG_TIME_T_UNSIGNED
 
 
 if test "$ac_cv_sizeof_unsigned_short" = "0" \
    || test "$ac_cv_sizeof_unsigned_int" = "0" \
    || test "$ac_cv_sizeof_unsigned_long" = "0"; then
     AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
 fi
 
 
 #
 # Checks for library functions.
 #
 AC_MSG_NOTICE([checking for library functions])
 AC_CHECK_DECLS(getpagesize)
 AC_FUNC_FSEEKO
 AC_FUNC_VPRINTF
 AC_FUNC_FORK
 AC_CHECK_FUNCS([strerror strlwr tcgetattr mmap canonicalize_file_name])
 AC_CHECK_FUNCS([strcasecmp strncasecmp ctermid times gmtime_r strtoull])
 AC_CHECK_FUNCS([setenv unsetenv fcntl ftruncate inet_ntop])
 AC_CHECK_FUNCS([canonicalize_file_name])
 AC_CHECK_FUNCS([gettimeofday getrusage getrlimit setrlimit clock_gettime])
 AC_CHECK_FUNCS([atexit raise getpagesize strftime nl_langinfo setlocale])
 AC_CHECK_FUNCS([waitpid wait4 sigaction sigprocmask pipe getaddrinfo])
 AC_CHECK_FUNCS([ttyname rand ftello fsync stat lstat])
 AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \
                 memrchr isascii timegm getrusage setrlimit stat setlocale   \
                 flockfile funlockfile getpwnam getpwuid \
                 getenv inet_pton strpbrk])
 
 # On some systems (e.g. Solaris) nanosleep requires linking to librl.
 # Given that we use nanosleep only as an optimization over a select
 # based wait function we want it only if it is available in libc.
 _save_libs="$LIBS"
 AC_SEARCH_LIBS([nanosleep], [],
                [AC_DEFINE(HAVE_NANOSLEEP,1,
                 [Define to 1 if you have the `nanosleep' function in libc.])])
 LIBS="$_save_libs"
 
 
 # See whether libc supports the Linux inotify interface
 case "${host}" in
     *-*-linux*)
         AC_CHECK_FUNCS([inotify_init])
         ;;
 esac
 
 
 if test "$have_android_system" = yes; then
    # On Android ttyname is a stub but prints an error message.
    AC_DEFINE(HAVE_BROKEN_TTYNAME,1,
              [Defined if ttyname does not work properly])
 fi
 
 AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>])
 
 # Dirmngr requires mmap on Unix systems.
 if test $ac_cv_func_mmap != yes -a $mmap_needed = yes; then
   AC_MSG_ERROR([[Sorry, the current implementation requires mmap.]])
 fi
 
 
 #
 # Check for the getsockopt SO_PEERCRED, etc.
 #
 AC_CHECK_MEMBERS([struct ucred.pid, struct ucred.cr_pid, struct sockpeercred.pid], [], [], [#include <sys/types.h>
 #include <sys/socket.h> ])
 
 # (Open)Solaris
 AC_CHECK_FUNCS([getpeerucred])
 
 
 #
 # W32 specific test
 #
 GNUPG_FUNC_MKDIR_TAKES_ONE_ARG
 
 #
 # Sanity check regex.  Tests adapted from mutt.
 #
 AC_MSG_CHECKING([whether regular expression support is requested])
 AC_ARG_ENABLE(regex,
   AC_HELP_STRING([--disable-regex],
     [do not handle regular expressions in trust signatures]),
   use_regex=$enableval, use_regex=yes)
 AC_MSG_RESULT($use_regex)
 
 if test "$use_regex" = yes ; then
   _cppflags="${CPPFLAGS}"
   _ldflags="${LDFLAGS}"
   AC_ARG_WITH(regex,
      AC_HELP_STRING([--with-regex=DIR],[look for regex in DIR]),
       [
       if test -d "$withval" ; then
         CPPFLAGS="${CPPFLAGS} -I$withval/include"
         LDFLAGS="${LDFLAGS} -L$withval/lib"
       fi
       ],withval="")
 
   # Does the system have regex functions at all?
   AC_SEARCH_LIBS([regcomp], [regex])
   AC_CHECK_FUNC(regcomp, gnupg_cv_have_regex=yes, gnupg_cv_have_regex=no)
 
   if test $gnupg_cv_have_regex = no; then
     use_regex=no
   else
     if test x"$cross_compiling" = xyes; then
       AC_MSG_WARN([cross compiling; assuming regexp libray is not broken])
     else
       AC_CACHE_CHECK([whether your system's regexp library is broken],
        [gnupg_cv_regex_broken],
        AC_TRY_RUN([
 #include <unistd.h>
 #include <regex.h>
 main() { regex_t blah ; regmatch_t p; p.rm_eo = p.rm_eo; return regcomp(&blah, "foo.*bar", REG_NOSUB) || regexec (&blah, "foobar", 0, NULL, 0); }],
        gnupg_cv_regex_broken=no, gnupg_cv_regex_broken=yes, gnupg_cv_regex_broken=yes))
 
       if test $gnupg_cv_regex_broken = yes; then
         AC_MSG_WARN([your regex is broken - disabling regex use])
         use_regex=no
       fi
     fi
   fi
   CPPFLAGS="${_cppflags}"
   LDFLAGS="${_ldflags}"
 fi
 
 if test "$use_regex" != yes ; then
   AC_DEFINE(DISABLE_REGEX,1, [Define to disable regular expression support])
 fi
 AM_CONDITIONAL(DISABLE_REGEX, test x"$use_regex" != xyes)
 
 
 
 #
 # Do we have zlib? Must do it here because Solaris failed
 # when compiling a conftest (due to the "-lz" from LIBS).
 # Note that we combine zlib and bzlib2 in ZLIBS.
 #
 if test "$use_zip" = yes ; then
   _cppflags="${CPPFLAGS}"
   _ldflags="${LDFLAGS}"
   AC_ARG_WITH(zlib,
     [  --with-zlib=DIR         use libz in DIR],[
       if test -d "$withval"; then
         CPPFLAGS="${CPPFLAGS} -I$withval/include"
         LDFLAGS="${LDFLAGS} -L$withval/lib"
       fi
     ])
 
   AC_CHECK_HEADER(zlib.h,
      AC_CHECK_LIB(z, deflateInit2_,
        [
        ZLIBS="-lz"
        AC_DEFINE(HAVE_ZIP,1, [Defined if ZIP and ZLIB are supported])
        ],
        CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}),
        CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags})
 fi
 
 
 #
 # Check whether we can support bzip2
 #
 if test "$use_bzip2" = yes ; then
   _cppflags="${CPPFLAGS}"
   _ldflags="${LDFLAGS}"
   AC_ARG_WITH(bzip2,
      AC_HELP_STRING([--with-bzip2=DIR],[look for bzip2 in DIR]),
       [
       if test -d "$withval" ; then
         CPPFLAGS="${CPPFLAGS} -I$withval/include"
         LDFLAGS="${LDFLAGS} -L$withval/lib"
       fi
       ],withval="")
 
   # Checking alongside stdio.h as an early version of bzip2 (1.0)
   # required stdio.h to be included before bzlib.h, and Solaris 9 is
   # woefully out of date.
   if test "$withval" != no ; then
      AC_CHECK_HEADER(bzlib.h,
         AC_CHECK_LIB(bz2,BZ2_bzCompressInit,
   	  [
 	  have_bz2=yes
 	  ZLIBS="$ZLIBS -lbz2"
 	  AC_DEFINE(HAVE_BZIP2,1,
 		  [Defined if the bz2 compression library is available])
 	  ],
 	  CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}),
 	  CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags},[#include <stdio.h>])
   fi
 fi
 AM_CONDITIONAL(ENABLE_BZIP2_SUPPORT,test x"$have_bz2" = "xyes")
 AC_SUBST(ZLIBS)
 
 
 # Check for readline support
 GNUPG_CHECK_READLINE
 
 
 if test "$development_version" = yes; then
     AC_DEFINE(IS_DEVELOPMENT_VERSION,1,
             [Defined if this is not a regular release])
 fi
 
 if test "$USE_MAINTAINER_MODE" = "yes"; then
     AC_DEFINE(MAINTAINER_MODE,1,
             [Defined if this build is in maintainer mode])
 fi
 
 AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
 
 GNUPG_CHECK_GNUMAKE
 
 # Add some extra libs here so that previous tests don't fail for
 # mysterious reasons - the final link step should bail out.
 # W32SOCKLIBS is also defined so that if can be used for tools not
 # requiring any network stuff but linking to code in libcommon which
 # tracks in winsock stuff (e.g. init_common_subsystems).
 if test "$have_w32_system" = yes; then
    if test "$have_w32ce_system" = yes; then
      W32SOCKLIBS="-lws2"
    else
      W32SOCKLIBS="-lws2_32"
    fi
    NETLIBS="${NETLIBS} ${W32SOCKLIBS}"
 fi
 
 AC_SUBST(NETLIBS)
 AC_SUBST(W32SOCKLIBS)
 
 #
 # Setup gcc specific options
 #
 USE_C99_CFLAGS=
 AC_MSG_NOTICE([checking for cc features])
 if test "$GCC" = yes; then
     mycflags=
     mycflags_save=$CFLAGS
 
     # Check whether gcc does not emit a diagnositc for unknown -Wno-*
     # options.  This is the case for gcc >= 4.6
     AC_MSG_CHECKING([if gcc ignores unknown -Wno-* options])
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6 )
 #kickerror
 #endif]],[])],[_gcc_silent_wno=yes],[_gcc_silent_wno=no])
     AC_MSG_RESULT($_gcc_silent_wno)
 
     # Note that it is okay to use CFLAGS here because these are just
     # warning options and the user should have a chance of overriding
     # them.
     if test "$USE_MAINTAINER_MODE" = "yes"; then
         mycflags="$mycflags -O3 -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
         mycflags="$mycflags -Wformat -Wno-format-y2k -Wformat-security"
         if test x"$_gcc_silent_wno" = xyes ; then
           _gcc_wopt=yes
         else
           AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
           CFLAGS="-Wno-missing-field-initializers"
           AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
                             [_gcc_wopt=yes],[_gcc_wopt=no])
           AC_MSG_RESULT($_gcc_wopt)
         fi
         if test x"$_gcc_wopt" = xyes ; then
           mycflags="$mycflags -W -Wno-sign-compare"
           mycflags="$mycflags -Wno-missing-field-initializers"
         fi
 
         AC_MSG_CHECKING([if gcc supports -Wdeclaration-after-statement])
         CFLAGS="-Wdeclaration-after-statement"
         AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
         AC_MSG_RESULT($_gcc_wopt)
         if test x"$_gcc_wopt" = xyes ; then
           mycflags="$mycflags -Wdeclaration-after-statement"
         fi
 
         AC_MSG_CHECKING([if gcc supports -Wlogical-op])
         CFLAGS="-Wlogical-op -Werror"
         AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
         AC_MSG_RESULT($_gcc_wopt)
         if test x"$_gcc_wopt" = xyes ; then
           mycflags="$mycflags -Wlogical-op"
         fi
 
         AC_MSG_CHECKING([if gcc supports -Wvla])
         CFLAGS="-Wvla"
         AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
         AC_MSG_RESULT($_gcc_wopt)
         if test x"$_gcc_wopt" = xyes ; then
           mycflags="$mycflags -Wvla"
         fi
 
     else
         mycflags="$mycflags -Wall"
     fi
 
     if test x"$_gcc_silent_wno" = xyes ; then
       _gcc_psign=yes
     else
       AC_MSG_CHECKING([if gcc supports -Wno-pointer-sign])
       CFLAGS="-Wno-pointer-sign"
       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
                         [_gcc_psign=yes],[_gcc_psign=no])
       AC_MSG_RESULT($_gcc_psign)
     fi
     if test x"$_gcc_psign" = xyes ; then
        mycflags="$mycflags -Wno-pointer-sign"
     fi
 
     AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
     CFLAGS="-Wpointer-arith"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_psign=yes,_gcc_psign=no)
     AC_MSG_RESULT($_gcc_psign)
     if test x"$_gcc_psign" = xyes ; then
        mycflags="$mycflags -Wpointer-arith"
     fi
 
     CFLAGS="$mycflags $mycflags_save"
     if test "$use_libdns" = yes; then
        # dirmngr/dns.{c,h} require C99 and GNU extensions.  */
        USE_C99_CFLAGS="-std=gnu99"
     fi
 fi
 
 AC_SUBST(USE_C99_CFLAGS)
 
 
 #
 # This is handy for debugging so the compiler doesn't rearrange
 # things and eliminate variables.
 #
 AC_ARG_ENABLE(optimization,
    AC_HELP_STRING([--disable-optimization],
                   [disable compiler optimization]),
                   [if test $enableval = no ; then
                       CFLAGS=`echo $CFLAGS | sed s/-O[[1-9]]\ /-O0\ /g`
                    fi])
 
 #
 # Add -Werror to CFLAGS.  This hack can be used to avoid problems with
 # misbehaving autoconf tests in case the user supplied -Werror.
 #
 AC_ARG_ENABLE(werror,
    AC_HELP_STRING([--enable-werror],
                   [append -Werror to CFLAGS]),
                   [if test $enableval = yes ; then
                       CFLAGS="$CFLAGS -Werror"
                    fi])
 
 #
 # Configure option --enable-all-tests
 #
 AC_MSG_CHECKING([whether "make check" shall run all tests])
 AC_ARG_ENABLE(all-tests,
               AC_HELP_STRING([--enable-all-tests],
                              [let "make check" run all tests]),
               run_all_tests=$enableval, run_all_tests=no)
 AC_MSG_RESULT($run_all_tests)
 if test "$run_all_tests" = "yes"; then
     AC_DEFINE(RUN_ALL_TESTS,1,
             [Defined if "make check" shall run all tests])
 fi
 
 #
 # We do not want support for the GNUPG_BUILDDIR environment variable
 # in a released version.  However, our regression tests suite requires
 # this and thus we build with support for it during "make distcheck".
 # This configure option implements this along with the top Makefile's
 # AM_DISTCHECK_CONFIGURE_FLAGS.
 #
 gnupg_builddir_envvar=no
 AC_ARG_ENABLE(gnupg-builddir-envvar,,
               gnupg_builddir_envvar=$enableval)
 if test x"$gnupg_builddir_envvar" = x"yes"; then
    AC_DEFINE(ENABLE_GNUPG_BUILDDIR_ENVVAR, 1,
       [This is only used with "make distcheck"])
 fi
 
 
 #
 # To avoid problems with systemd cleaning up the /run/user directory,
 # this option will make GnuPG try to use /run/gnupg/user as socket dir
 # before /run/user
 #
 AC_ARG_ENABLE(run-gnupg-user-socket,
     AC_HELP_STRING([--enable-run-gnupg-user-socket],
                    [try /run/gnupg/user for sockets prior to /run/user]),
     use_run_gnupg_user_socket=$enableval)
 if test x"$use_run_gnupg_user_socket" = x"yes"; then
    AC_DEFINE(USE_RUN_GNUPG_USER_SOCKET, 1,
             [If defined try /run/gnupg/user before /run/user])
 fi
 
 
 #
 # Decide what to build
 #
 
 build_scdaemon_extra=""
 if test "$build_scdaemon" = "yes"; then
   if test $have_libusb = no; then
      build_scdaemon_extra="without internal CCID driver"
   fi
   if test -n "$build_scdaemon_extra"; then
      build_scdaemon_extra="(${build_scdaemon_extra})"
   fi
 fi
 
 
 #
 # Set variables for use by automake makefiles.
 #
 AM_CONDITIONAL(BUILD_GPG,         test "$build_gpg" = "yes")
 AM_CONDITIONAL(BUILD_GPGSM,       test "$build_gpgsm" = "yes")
 AM_CONDITIONAL(BUILD_AGENT,       test "$build_agent" = "yes")
 AM_CONDITIONAL(BUILD_SCDAEMON,    test "$build_scdaemon" = "yes")
 AM_CONDITIONAL(BUILD_G13,         test "$build_g13" = "yes")
 AM_CONDITIONAL(BUILD_DIRMNGR,     test "$build_dirmngr" = "yes")
 AM_CONDITIONAL(BUILD_DOC,         test "$build_doc" = "yes")
 AM_CONDITIONAL(BUILD_SYMCRYPTRUN, test "$build_symcryptrun" = "yes")
 AM_CONDITIONAL(BUILD_GPGTAR,      test "$build_gpgtar" = "yes")
 AM_CONDITIONAL(BUILD_WKS_TOOLS,   test "$build_wks_tools" = "yes")
 
 AM_CONDITIONAL(ENABLE_CARD_SUPPORT, test "$card_support" = yes)
 AM_CONDITIONAL(NO_TRUST_MODELS,     test "$use_trust_models" = no)
 AM_CONDITIONAL(USE_TOFU,            test "$use_tofu" = yes)
 
 #
 # Set some defines for use gpgconf.
 #
 if test "$build_gpg" = yes ; then
     AC_DEFINE(BUILD_WITH_GPG,1,[Defined if GPG is to be build])
 fi
 if test "$build_gpgsm" = yes ; then
     AC_DEFINE(BUILD_WITH_GPGSM,1,[Defined if GPGSM is to be build])
 fi
 if test "$build_agent" = yes ; then
     AC_DEFINE(BUILD_WITH_AGENT,1,[Defined if GPG-AGENT is to be build])
 fi
 if test "$build_scdaemon" = yes ; then
     AC_DEFINE(BUILD_WITH_SCDAEMON,1,[Defined if SCDAEMON is to be build])
 fi
 if test "$build_dirmngr" = yes ; then
     AC_DEFINE(BUILD_WITH_DIRMNGR,1,[Defined if DIRMNGR is to be build])
 fi
 if test "$build_g13" = yes ; then
     AC_DEFINE(BUILD_WITH_G13,1,[Defined if G13 is to be build])
 fi
 
 
 #
 # Define Name strings
 #
 AC_DEFINE_UNQUOTED(GNUPG_NAME, "GnuPG", [The name of the project])
 
 AC_DEFINE_UNQUOTED(GPG_NAME, "gpg", [The name of the OpenPGP tool])
 AC_DEFINE_UNQUOTED(GPG_DISP_NAME, "GnuPG", [The displayed name of gpg])
 
 AC_DEFINE_UNQUOTED(GPGSM_NAME, "gpgsm", [The name of the S/MIME tool])
 AC_DEFINE_UNQUOTED(GPGSM_DISP_NAME, "GPGSM", [The displayed name of gpgsm])
 
 AC_DEFINE_UNQUOTED(GPG_AGENT_NAME, "gpg-agent", [The name of the agent])
 AC_DEFINE_UNQUOTED(GPG_AGENT_DISP_NAME, "GPG Agent",
                                         [The displayed name of gpg-agent])
 
 AC_DEFINE_UNQUOTED(SCDAEMON_NAME, "scdaemon", [The name of the scdaemon])
 AC_DEFINE_UNQUOTED(SCDAEMON_DISP_NAME, "SCDaemon",
                                        [The displayed name of scdaemon])
 
 AC_DEFINE_UNQUOTED(DIRMNGR_NAME, "dirmngr", [The name of the dirmngr])
 AC_DEFINE_UNQUOTED(DIRMNGR_DISP_NAME, "DirMngr",
                                       [The displayed name of dirmngr])
 
 AC_DEFINE_UNQUOTED(G13_NAME, "g13", [The name of the g13 tool])
 AC_DEFINE_UNQUOTED(G13_DISP_NAME, "G13", [The displayed name of g13])
 
 AC_DEFINE_UNQUOTED(GPGCONF_NAME, "gpgconf", [The name of the gpgconf tool])
 AC_DEFINE_UNQUOTED(GPGCONF_DISP_NAME, "GPGConf",
                                       [The displayed name of gpgconf])
 
 AC_DEFINE_UNQUOTED(GPGTAR_NAME, "gpgtar", [The name of the gpgtar tool])
 
 AC_DEFINE_UNQUOTED(GPG_AGENT_SOCK_NAME, "S.gpg-agent",
                    [The name of the agent socket])
 AC_DEFINE_UNQUOTED(GPG_AGENT_EXTRA_SOCK_NAME, "S.gpg-agent.extra",
                    [The name of the agent socket for remote access])
 AC_DEFINE_UNQUOTED(GPG_AGENT_BROWSER_SOCK_NAME, "S.gpg-agent.browser",
                    [The name of the agent socket for browsers])
 AC_DEFINE_UNQUOTED(GPG_AGENT_SSH_SOCK_NAME, "S.gpg-agent.ssh",
                    [The name of the agent socket for ssh])
 AC_DEFINE_UNQUOTED(DIRMNGR_INFO_NAME, "DIRMNGR_INFO",
                    [The name of the dirmngr info envvar])
 AC_DEFINE_UNQUOTED(SCDAEMON_SOCK_NAME, "S.scdaemon",
                    [The name of the SCdaemon socket])
 AC_DEFINE_UNQUOTED(DIRMNGR_SOCK_NAME, "S.dirmngr",
                    [The name of the dirmngr socket])
 AC_DEFINE_UNQUOTED(DIRMNGR_DEFAULT_KEYSERVER,
                    "hkps://hkps.pool.sks-keyservers.net",
       [The default keyserver for dirmngr to use, if none is explicitly given])
 
 AC_DEFINE_UNQUOTED(GPGEXT_GPG, "gpg", [The standard binary file suffix])
 
 if test "$have_w32_system" = yes; then
   AC_DEFINE_UNQUOTED(GNUPG_REGISTRY_DIR, "Software\\\\GNU\\\\GnuPG",
                      [The directory part of the W32 registry keys])
 fi
 
 
 #
 # Provide information about the build.
 #
 BUILD_REVISION="mym4_revision"
 AC_SUBST(BUILD_REVISION)
 AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION",
                    [GIT commit id revision used to build this package])
 
 changequote(,)dnl
 BUILD_VERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./'`
 changequote([,])dnl
 BUILD_VERSION="${BUILD_VERSION}mym4_revision_dec"
 BUILD_FILEVERSION=`echo "${BUILD_VERSION}" | tr . ,`
 AC_SUBST(BUILD_VERSION)
 AC_SUBST(BUILD_FILEVERSION)
 
 AC_ARG_ENABLE([build-timestamp],
   AC_HELP_STRING([--enable-build-timestamp],
                  [set an explicit build timestamp for reproducibility.
                   (default is the current time in ISO-8601 format)]),
      [if test "$enableval" = "yes"; then
         BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date`
       else
         BUILD_TIMESTAMP="$enableval"
       fi
       BUILD_HOSTNAME="$ac_hostname"],
      [BUILD_TIMESTAMP="<none>"
       BUILD_HOSTNAME="<anon>"])
 AC_SUBST(BUILD_TIMESTAMP)
 AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
                    [The time this package was configured for a build])
 AC_SUBST(BUILD_HOSTNAME)
 
 
 #
 # Print errors here so that they are visible all
 # together and the user can acquire them all together.
 #
 die=no
 if test "$have_gpg_error" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
 ***
 *** You need libgpg-error to build this program.
 **  This library is for example available at
 ***   https://gnupg.org/ftp/gcrypt/libgpg-error
 *** (at least version $NEED_GPG_ERROR_VERSION is required.)
 ***]])
 fi
 if test "$have_libgcrypt" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
 ***
 *** You need libgcrypt to build this program.
 **  This library is for example available at
 ***   https://gnupg.org/ftp/gcrypt/libgcrypt/
 *** (at least version $NEED_LIBGCRYPT_VERSION (API $NEED_LIBGCRYPT_API) is required.)
 ***]])
 fi
 if test "$have_libassuan" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
 ***
 *** You need libassuan to build this program.
 *** This library is for example available at
 ***   https://gnupg.org/ftp/gcrypt/libassuan/
 *** (at least version $NEED_LIBASSUAN_VERSION (API $NEED_LIBASSUAN_API) is required).
 ***]])
 fi
 if test "$have_ksba" = "no"; then
     die=yes
     AC_MSG_NOTICE([[
 ***
 *** You need libksba to build this program.
 *** This library is for example available at
 ***   https://gnupg.org/ftp/gcrypt/libksba/
 *** (at least version $NEED_KSBA_VERSION using API $NEED_KSBA_API is required).
 ***]])
 fi
 if test "$gnupg_have_ldap" = yes; then
   if test "$have_w32ce_system" = yes; then
     AC_MSG_NOTICE([[
 *** Note that CeGCC might be broken, a package fixing this is:
 ***    http://files.kolab.org/local/windows-ce/
 ***                           source/wldap32_0.1-mingw32ce.orig.tar.gz
 ***                           binary/wldap32-ce-arm-dev_0.1-1_all.deb
 ***]])
    fi
 fi
 if test "$have_npth" = "no"; then
     die=yes
     AC_MSG_NOTICE([[
 ***
 *** It is now required to build with support for the
 *** New Portable Threads Library (nPth). Please install this
 *** library first.  The library is for example available at
 ***   https://gnupg.org/ftp/gcrypt/npth/
 *** (at least version $NEED_NPTH_VERSION (API $NEED_NPTH_API) is required).
 ***]])
 fi
 
 if test "$require_iconv" = yes; then
   if test "$am_func_iconv" != yes; then
     die=yes
     AC_MSG_NOTICE([[
 ***
 *** The system does not provide a working iconv function.  Please
 *** install a suitable library; for example GNU Libiconv which is
 *** available at:
 ***   https://ftp.gnu.org/gnu/libiconv/
 ***]])
   fi
 fi
 
 if test "$use_ccid_driver" = yes; then
   if test "$have_libusb" != yes; then
     die=yes
     AC_MSG_NOTICE([[
 ***
 *** You need libusb to build the internal ccid driver.  Please
 *** install a libusb suitable for your system.
 ***]])
   fi
 fi
 
 if test "$die" = "yes"; then
     AC_MSG_ERROR([[
 ***
 *** Required libraries not found. Please consult the above messages
 *** and install them before running configure again.
 ***]])
 fi
 
 
 
 AC_CONFIG_FILES([ m4/Makefile
 Makefile
 po/Makefile.in
 common/Makefile
 common/w32info-rc.h
 kbx/Makefile
 g10/Makefile
 sm/Makefile
 agent/Makefile
 scd/Makefile
 g13/Makefile
 dirmngr/Makefile
 tools/gpg-zip
 tools/Makefile
 doc/Makefile
 tests/Makefile
 tests/gpgscm/Makefile
 tests/openpgp/Makefile
 tests/migrations/Makefile
 tests/gpgsm/Makefile
 tests/gpgme/Makefile
 tests/pkits/Makefile
 g10/gpg.w32-manifest
 ])
 
 
 AC_OUTPUT
 
 
 echo "
         GnuPG v${VERSION} has been configured as follows:
 
         Revision:  mym4_revision  (mym4_revision_dec)
         Platform:  $PRINTABLE_OS_NAME ($host)
 
         OpenPGP:   $build_gpg
         S/MIME:    $build_gpgsm
         Agent:     $build_agent
         Smartcard: $build_scdaemon $build_scdaemon_extra
         G13:       $build_g13
         Dirmngr:   $build_dirmngr
         Gpgtar:    $build_gpgtar
         WKS tools: $build_wks_tools
 
         Protect tool:      $show_gnupg_protect_tool_pgm
         LDAP wrapper:      $show_gnupg_dirmngr_ldap_pgm
         Default agent:     $show_gnupg_agent_pgm
         Default pinentry:  $show_gnupg_pinentry_pgm
         Default scdaemon:  $show_gnupg_scdaemon_pgm
         Default dirmngr:   $show_gnupg_dirmngr_pgm
 
         Dirmngr auto start:  $dirmngr_auto_start
         Readline support:    $gnupg_cv_have_readline
         LDAP support:        $gnupg_have_ldap
         TLS support:         $use_tls_library
         TOFU support:        $use_tofu
         Tor support:         $show_tor_support
 "
 if test x"$use_regex" != xyes ; then
 echo "
         Warning: No regular expression support available.
                  OpenPGP trust signatures won't work.
                  gpg-check-pattern will not be built.
 "
 fi
 if test "x${gpg_config_script_warn}" != x; then
 cat <<G10EOF
         Warning: Mismatches between the target platform and the
                  to be used libraries have been detected for:
                   ${gpg_config_script_warn}
                  Please check above for more warning messages.
 
 G10EOF
 fi