示例#1
0
static gpg_error_t
create_pipe_and_estream (int filedes[2], estream_t *r_fp,
                         gpg_err_source_t errsource)
{
    gpg_error_t err;

    if (pipe (filedes) == -1)
    {
        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
        log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
        filedes[0] = filedes[1] = -1;
        *r_fp = NULL;
        return err;
    }

    *r_fp = es_fdopen (filedes[0], "r");
    if (!*r_fp)
    {
        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
        log_error (_("error creating a stream for a pipe: %s\n"),
                   gpg_strerror (err));
        close (filedes[0]);
        close (filedes[1]);
        filedes[0] = filedes[1] = -1;
        return err;
    }
    return 0;
}
示例#2
0
/* Compute the A value as used by EdDSA.  The caller needs to provide
   the context EC and the actual secret D as an MPI.  The function
   returns a newly allocated 64 byte buffer at r_digest; the first 32
   bytes represent the A value.  NULL is returned on error and NULL
   stored at R_DIGEST.  */
gpg_err_code_t
_gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
                             gcry_mpi_t d, mpi_ec_t ec)
{
  gpg_err_code_t rc;
  unsigned char *rawmpi = NULL;
  unsigned int rawmpilen;
  unsigned char *digest;
  gcry_buffer_t hvec[2];
  int hashalgo, b;

  *r_digest = NULL;

  hashalgo = GCRY_MD_SHA512;
  if (hashalgo != GCRY_MD_SHA512)
    return GPG_ERR_DIGEST_ALGO;

  b = (ec->nbits+7)/8;
  if (b != 256/8)
    return GPG_ERR_INTERNAL; /* We only support 256 bit. */

  /* Note that we clear DIGEST so we can use it as input to left pad
     the key with zeroes for hashing.  */
  digest = xtrycalloc_secure (2, b);
  if (!digest)
    return gpg_err_code_from_syserror ();

  memset (hvec, 0, sizeof hvec);

  rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
  if (!rawmpi)
    {
      xfree (digest);
      return gpg_err_code_from_syserror ();
    }

  hvec[0].data = digest;
  hvec[0].off = 0;
  hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
  hvec[1].data = rawmpi;
  hvec[1].off = 0;
  hvec[1].len = rawmpilen;
  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
  xfree (rawmpi);
  if (rc)
    {
      xfree (digest);
      return rc;
    }

  /* Compute the A value.  */
  reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
  digest[0]   = (digest[0] & 0x7f) | 0x40;
  digest[31] &= 0xf8;

  *r_digest = digest;
  return 0;
}
示例#3
0
int
main (int argc, char *argv[])
{
  FILE *fp;
  int save_errno;
  gpg_err_code_t ec;

  fp = fopen ("/does-not-exist/110761/nowhere.foo", "r");
  if (fp)
    {
      fclose (fp);
      fp = fopen ("  no this file does not exists foo 4711", "r");
    }
  if (fp)
    {
      fprintf (stderr, "unable to run test\n");
      return 1;
    }
  save_errno = errno;

  ec = gpg_err_code_from_syserror ();
  if (ec != GPG_ERR_ENOENT)
    {
      fprintf (stderr, "fopen failed with bad code: %d\n", save_errno);
      return 1;
    }

  if (ec != gpg_err_code_from_errno (save_errno))
    {
      fprintf (stderr, "oops at %d\n",__LINE__);
      return 1;
    }

  gpg_err_set_errno (0);

  ec = gpg_err_code_from_syserror ();
  if (ec != GPG_ERR_MISSING_ERRNO)
    {
      fprintf (stderr, "oops at %d\n",__LINE__);
      return 1;
    }

  if ( gpg_err_code_from_errno (0) )
    {
      fprintf (stderr, "oops at %d\n",__LINE__);
      return 1;
    }


  return 0;
}
示例#4
0
gpg_error_t
_assuan_write_line (assuan_context_t ctx, const char *prefix,
                    const char *line, size_t len)
{
  gpg_error_t rc = 0;
  size_t prefixlen = prefix? strlen (prefix):0;
  unsigned int monitor_result;

  /* Make sure that the line is short enough. */
  if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
    {
      _assuan_log_control_channel (ctx, 1,
                                   "supplied line too long - truncated",
                                   NULL, 0, NULL, 0);
      if (prefixlen > 5)
        prefixlen = 5;
      if (len > ASSUAN_LINELENGTH - prefixlen - 2)
        len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
    }

  monitor_result = 0;
  if (ctx->io_monitor)
    monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1, line, len);

  /* Fixme: we should do some kind of line buffering.  */
  if (!(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
    _assuan_log_control_channel (ctx, 1, NULL,
                                 prefixlen? prefix:NULL, prefixlen,
                                 line, len);

  if (prefixlen && !(monitor_result & ASSUAN_IO_MONITOR_IGNORE))
    {
      rc = writen (ctx, prefix, prefixlen);
      if (rc)
	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
    }
  if (!rc && !(monitor_result & ASSUAN_IO_MONITOR_IGNORE))
    {
      rc = writen (ctx, line, len);
      if (rc)
	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
      if (!rc)
        {
          rc = writen (ctx, "\n", 1);
          if (rc)
	    rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
        }
    }
  return rc;
}
示例#5
0
static gpg_error_t
cmd_verify (assuan_context_t ctx, char *line)
{
  int rc;
  ctrl_t ctrl = assuan_get_pointer (ctx);
  int fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
  int out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
  estream_t out_fp = NULL;

  (void)line;

  if (fd == -1)
    return set_error (GPG_ERR_ASS_NO_INPUT, NULL);

  if (out_fd != -1)
    {
      out_fp = es_fdopen_nc (out_fd, "w");
      if (!out_fp)
        return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
    }

  rc = start_audit_session (ctrl);
  if (!rc)
    rc = gpgsm_verify (assuan_get_pointer (ctx), fd,
                       ctrl->server_local->message_fd, out_fp);
  es_fclose (out_fp);

  /* Close and reset the fd.  */
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);

  return rc;
}
示例#6
0
static gpg_error_t
cmd_message (assuan_context_t ctx, char *line)
{
  int rc;
  gnupg_fd_t sysfd;
  int fd;
  ctrl_t ctrl = assuan_get_pointer (ctx);

  rc = assuan_command_parse_fd (ctx, line, &sysfd);
  if (rc)
    return rc;

#ifdef HAVE_W32CE_SYSTEM
  sysfd = _assuan_w32ce_finish_pipe ((int)sysfd, 0);
  if (sysfd == INVALID_HANDLE_VALUE)
    return set_error (gpg_err_code_from_syserror (),
		      "rvid conversion failed");
#endif

  fd = translate_sys2libc_fd (sysfd, 0);
  if (fd == -1)
    return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
  ctrl->server_local->message_fd = fd;
  return 0;
}
示例#7
0
/* Format is OUTPUT FD=<n> */
static gpg_error_t
std_handler_output (assuan_context_t ctx, char *line)
{
  gpg_error_t rc;
  assuan_fd_t fd, oldfd;

  rc = assuan_command_parse_fd (ctx, line, &fd);
  if (rc)
    return PROCESS_DONE (ctx, rc);

#ifdef HAVE_W32CE_SYSTEM
  oldfd = fd;
  fd = _assuan_w32ce_finish_pipe ((int)fd, 1);
  if (fd == INVALID_HANDLE_VALUE)
    return PROCESS_DONE (ctx, set_error (ctx, gpg_err_code_from_syserror (),
					 "rvid conversion failed"));
  TRACE2 (ctx, ASSUAN_LOG_SYSIO, "std_handler_output", ctx,
	  "turned RVID 0x%x into handle 0x%x", oldfd, fd);
#endif

  if (ctx->output_notify_fnc)
    {
      oldfd = ctx->output_fd;
      ctx->output_fd = fd;
      rc = ctx->output_notify_fnc (ctx, line);
      if (rc)
        ctx->output_fd = oldfd;
    }
  else if (!rc)
    ctx->output_fd = fd;
  return PROCESS_DONE (ctx, rc);
}
示例#8
0
/* Turn VALUE into an octet string and store it in an allocated buffer
   at R_FRAME.  If the resulting octet string is shorter than NBYTES
   the result will be left padded with zeroes.  If VALUE does not fit
   into NBYTES an error code is returned.  */
static gpg_err_code_t
int2octets (unsigned char **r_frame, gcry_mpi_t value, size_t nbytes)
{
  gpg_err_code_t rc;
  size_t nframe, noff, n;
  unsigned char *frame;

  rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value);
  if (rc)
    return rc;
  if (nframe > nbytes)
    return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES.  */

  noff = (nframe < nbytes)? nbytes - nframe : 0;
  n = nframe + noff;
  frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n);
  if (!frame)
    return gpg_err_code_from_syserror ();
  if (noff)
    memset (frame, 0, noff);
  nframe += noff;
  rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value);
  if (rc)
    {
      xfree (frame);
      return rc;
    }

  *r_frame = frame;
  return 0;
}
示例#9
0
static gpg_error_t
cmd_decrypt (assuan_context_t ctx, char *line)
{
  ctrl_t ctrl = assuan_get_pointer (ctx);
  int inp_fd, out_fd;
  estream_t out_fp;
  int rc;

  (void)line;

  inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
  if (inp_fd == -1)
    return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
  out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
  if (out_fd == -1)
    return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);

  out_fp = es_fdopen_nc (out_fd, "w");
  if (!out_fp)
    return set_error (gpg_err_code_from_syserror (), "fdopen() failed");

  rc = start_audit_session (ctrl);
  if (!rc)
    rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
  es_fclose (out_fp);

  /* Close and reset the fds. */
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);

  return rc;
}
示例#10
0
/* Give the name of the curve NAME, store the curve parameters into P,
   A, B, G, and N if they point to NULL value.  Note that G is returned
   in standard uncompressed format.  Also update MODEL and DIALECT if
   they are not NULL. */
gpg_err_code_t
_gcry_ecc_update_curve_param (const char *name,
                              enum gcry_mpi_ec_models *model,
                              enum ecc_dialects *dialect,
                              gcry_mpi_t *p, gcry_mpi_t *a, gcry_mpi_t *b,
                              gcry_mpi_t *g, gcry_mpi_t *n)
{
  int idx;

  idx = find_domain_parms_idx (name);
  if (idx < 0)
    return GPG_ERR_UNKNOWN_CURVE;

  if (g)
    {
      char *buf;
      size_t len;

      len = 4;
      len += strlen (domain_parms[idx].g_x+2);
      len += strlen (domain_parms[idx].g_y+2);
      len++;
      buf = xtrymalloc (len);
      if (!buf)
        return gpg_err_code_from_syserror ();
      strcpy (stpcpy (stpcpy (buf, "0x04"), domain_parms[idx].g_x+2),
              domain_parms[idx].g_y+2);
      _gcry_mpi_release (*g);
      *g = scanval (buf);
      xfree (buf);
    }
  if (model)
    *model = domain_parms[idx].model;
  if (dialect)
    *dialect = domain_parms[idx].dialect;
  if (p)
    {
      _gcry_mpi_release (*p);
      *p = scanval (domain_parms[idx].p);
    }
  if (a)
    {
      _gcry_mpi_release (*a);
      *a = scanval (domain_parms[idx].a);
    }
  if (b)
    {
      _gcry_mpi_release (*b);
      *b = scanval (domain_parms[idx].b);
    }
  if (n)
    {
      _gcry_mpi_release (*n);
      *n = scanval (domain_parms[idx].n);
    }
  return 0;
}
示例#11
0
/* Make sure that the opaque MPI VALUE is in compact EdDSA format.
   This function updates MPI if needed.  */
gpg_err_code_t
_gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value, unsigned int nbits)
{
  gpg_err_code_t rc;
  const unsigned char *buf;
  unsigned int rawmpilen;
  gcry_mpi_t x, y;
  unsigned char *enc;
  unsigned int enclen;

  if (!mpi_is_opaque (value))
    return GPG_ERR_INV_OBJ;
  buf = mpi_get_opaque (value, &rawmpilen);
  if (!buf)
    return GPG_ERR_INV_OBJ;
  rawmpilen = (rawmpilen + 7)/8;

  if (rawmpilen > 1 && (rawmpilen%2))
    {
      if (buf[0] == 0x04)
        {
          /* Buffer is in SEC1 uncompressed format.  Extract y and
             compress.  */
          rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
                               buf+1, (rawmpilen-1)/2, NULL);
          if (rc)
            return rc;
          rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
                               buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2, NULL);
          if (rc)
            {
              mpi_free (x);
              return rc;
            }

          rc = eddsa_encode_x_y (x, y, nbits/8, 0, &enc, &enclen);
          mpi_free (x);
          mpi_free (y);
          if (rc)
            return rc;

          mpi_set_opaque (value, enc, 8*enclen);
        }
      else if (buf[0] == 0x40)
        {
          /* Buffer is compressed but with our SEC1 alike compression
             indicator.  Remove that byte.  FIXME: We should write and
             use a function to manipulate an opaque MPI in place. */
          if (!_gcry_mpi_set_opaque_copy (value, buf + 1, (rawmpilen - 1)*8))
            return gpg_err_code_from_syserror ();
        }
    }

  return 0;
}
示例#12
0
static gpg_error_t
uds_sendfd (assuan_context_t ctx, assuan_fd_t fd)
{
#ifdef USE_DESCRIPTOR_PASSING
  struct msghdr msg;
  struct iovec iovec;
  union {
    struct cmsghdr cm;
    char control[CMSG_SPACE(sizeof (int))];
  } control_u;
  struct cmsghdr *cmptr;
  int len;
  char buffer[80];

  /* We need to send some real data so that a read won't return 0
     which will be taken as an EOF.  It also helps with debugging. */
  snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd);
  buffer[sizeof(buffer)-1] = 0;

  memset (&msg, 0, sizeof (msg));

  memset (&control_u, 0, sizeof (control_u));

  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_iovlen = 1;
  msg.msg_iov = &iovec;
  iovec.iov_base = buffer;
  iovec.iov_len = strlen (buffer);

  msg.msg_control = control_u.control;
  msg.msg_controllen = sizeof (control_u.control);
  cmptr = CMSG_FIRSTHDR (&msg);
  cmptr->cmsg_len = CMSG_LEN(sizeof(int));
  cmptr->cmsg_level = SOL_SOCKET;
  cmptr->cmsg_type = SCM_RIGHTS;

  memcpy (CMSG_DATA (cmptr), &fd, sizeof (fd));

  len = _assuan_sendmsg (ctx, ctx->outbound.fd, &msg, 0);
  if (len < 0)
    {
      int saved_errno = errno;
      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "uds_sendfd", ctx,
	      "uds_sendfd: %s", strerror (errno));
      errno = saved_errno;
      return _assuan_error (ctx, gpg_err_code_from_syserror ());
    }
  else
    return 0;
#else
  return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
#endif
}
示例#13
0
文件: server.c 项目: Distrotech/gnupg
/*  VERIFY

   This does a verify operation on the message send to the input-FD.
   The result is written out using status lines.  If an output FD was
   given, the signed text will be written to that.

   If the signature is a detached one, the server will inquire about
   the signed material and the client must provide it.
 */
static gpg_error_t
cmd_verify (assuan_context_t ctx, char *line)
{
  int rc;
#ifdef HAVE_W32_SYSTEM
  (void)ctx;
  (void)line;
  rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
#else
  ctrl_t ctrl = assuan_get_pointer (ctx);
  gnupg_fd_t fd = assuan_get_input_fd (ctx);
  gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
  estream_t out_fp = NULL;

  /* FIXME: Revamp this code it is nearly to 3 years old and was only
     intended as a quick test.  */

  (void)line;

  if (fd == GNUPG_INVALID_FD)
    return gpg_error (GPG_ERR_ASS_NO_INPUT);

  if (out_fd != GNUPG_INVALID_FD)
    {
      es_syshd_t syshd;

#ifdef HAVE_W32_SYSTEM
      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = out_fd;
#else
      syshd.type = ES_SYSHD_FD;
      syshd.u.fd = out_fd;
#endif
      out_fp = es_sysopen_nc (&syshd, "w");
      if (!out_fp)
        return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
    }

  log_debug ("WARNING: The server mode is WORK "
             "IN PROGRESS and not ready for use\n");

  rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);

  es_fclose (out_fp);
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);
#endif

  if (rc)
    log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
  return rc;
}
示例#14
0
/* Encode MPI using the EdDSA scheme.  MINLEN specifies the required
   length of the buffer in bytes.  On success 0 is returned an a
   malloced buffer with the encoded point is stored at R_BUFFER; the
   length of this buffer is stored at R_BUFLEN.  */
static gpg_err_code_t
eddsa_encodempi (gcry_mpi_t mpi, unsigned int minlen,
                 unsigned char **r_buffer, unsigned int *r_buflen)
{
  unsigned char *rawmpi;
  unsigned int rawmpilen;

  rawmpi = _gcry_mpi_get_buffer (mpi, minlen, &rawmpilen, NULL);
  if (!rawmpi)
    return gpg_err_code_from_syserror ();

  *r_buffer = rawmpi;
  *r_buflen = rawmpilen;
  return 0;
}
示例#15
0
static gpg_error_t
cmd_encrypt (assuan_context_t ctx, char *line)
{
  ctrl_t ctrl = assuan_get_pointer (ctx);
  certlist_t cl;
  int inp_fd, out_fd;
  estream_t out_fp;
  int rc;

  (void)line;

  inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
  if (inp_fd == -1)
    return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
  out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
  if (out_fd == -1)
    return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);

  out_fp = es_fdopen_nc (out_fd, "w");
  if (!out_fp)
    return set_error (gpg_err_code_from_syserror (), "fdopen() failed");

  /* Now add all encrypt-to marked recipients from the default
     list. */
  rc = 0;
  if (!opt.no_encrypt_to && !ctrl->server_local->no_encrypt_to)
    {
      for (cl=ctrl->server_local->default_recplist; !rc && cl; cl = cl->next)
        if (cl->is_encrypt_to)
          rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert,
                                           &ctrl->server_local->recplist, 1);
    }
  if (!rc)
    rc = ctrl->audit? 0 : start_audit_session (ctrl);
  if (!rc)
    rc = gpgsm_encrypt (assuan_get_pointer (ctx),
                        ctrl->server_local->recplist,
                        inp_fd, out_fp);
  es_fclose (out_fp);

  gpgsm_release_certlist (ctrl->server_local->recplist);
  ctrl->server_local->recplist = NULL;
  /* Close and reset the fd */
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);
  return rc;
}
示例#16
0
文件: ec.c 项目: Greenchik/libgcrypt
/* This function returns a new context for elliptic curve operations
   based on the field GF(p).  P is the prime specifying this field, A
   is the first coefficient.  On success the new context is stored at
   R_CTX and 0 is returned; on error NULL is stored at R_CTX and an
   error code is returned.  The context needs to be released using
   gcry_ctx_release.  This is an internal fucntions.  */
gpg_err_code_t
_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
{
  gcry_ctx_t ctx;
  mpi_ec_t ec;

  *r_ctx = NULL;
  if (!p || !a || !mpi_cmp_ui (a, 0))
    return GPG_ERR_EINVAL;

  ctx = _gcry_ctx_alloc (CONTEXT_TYPE_EC, sizeof *ec, ec_deinit);
  if (!ctx)
    return gpg_err_code_from_syserror ();
  ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
  ec_p_init (ec, p, a);

  *r_ctx = ctx;
  return 0;
}
示例#17
0
/* Extended version of ecc_generate which is called directly by
   pubkey.c.  If CURVE is not NULL, that name will be used to select
   the domain parameters.  NBITS is not used in this case.  */
gcry_err_code_t
_gcry_ecc_generate (int algo, unsigned int nbits, const char *curve,
                    gcry_mpi_t *skey, gcry_mpi_t **retfactors)
{
  gpg_err_code_t err;
  ECC_secret_key sk;
  gcry_mpi_t g_x, g_y, q_x, q_y;

  (void)algo;

  /* Make an empty list of factors.  */
  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
  if (!*retfactors)
    return gpg_err_code_from_syserror ();

  g_x = mpi_new (0);
  g_y = mpi_new (0);
  q_x = mpi_new (0);
  q_y = mpi_new (0);
  err = generate_key (&sk, nbits, curve, g_x, g_y, q_x, q_y);
  if (err)
    {
      gcry_free (*retfactors);
      *retfactors = NULL;
      return err;
    }

  skey[0] = sk.E.p;
  skey[1] = sk.E.a;
  skey[2] = sk.E.b;
  /* The function ec2os releases g_x and g_y.  */
  skey[3] = ec2os (g_x, g_y, sk.E.p);
  skey[4] = sk.E.n;
  /* The function ec2os releases g_x and g_y.  */
  skey[5] = ec2os (q_x, q_y, sk.E.p);
  skey[6] = sk.d;

  point_free (&sk.E.G);
  point_free (&sk.Q);

  return 0;
}
示例#18
0
/* Encode (X,Y) using the EdDSA scheme.  MINLEN is the required length
   in bytes for the result.  If WITH_PREFIX is set the returned buffer
   is prefixed with a 0x40 byte.  On success 0 is returned and a
   malloced buffer with the encoded point is stored at R_BUFFER; the
   length of this buffer is stored at R_BUFLEN.  */
static gpg_err_code_t
eddsa_encode_x_y (gcry_mpi_t x, gcry_mpi_t y, unsigned int minlen,
                  int with_prefix,
                  unsigned char **r_buffer, unsigned int *r_buflen)
{
  unsigned char *rawmpi;
  unsigned int rawmpilen;
  int off = with_prefix? 1:0;

  rawmpi = _gcry_mpi_get_buffer_extra (y, minlen, off?-1:0, &rawmpilen, NULL);
  if (!rawmpi)
    return gpg_err_code_from_syserror ();
  if (mpi_test_bit (x, 0) && rawmpilen)
    rawmpi[off + rawmpilen - 1] |= 0x80;  /* Set sign bit.  */
  if (off)
    rawmpi[0] = 0x40;

  *r_buffer = rawmpi;
  *r_buflen = rawmpilen + off;
  return 0;
}
示例#19
0
/**
 * assuan_inquire_ext:
 * @ctx: An assuan context
 * @keyword: The keyword used for the inquire
 * @maxlen: If not 0, the size limit of the inquired data.
 * @cb: A callback handler which is invoked after the operation completed.
 * @cb_data: A user-provided value passed to the callback handler.
 * 
 * A Server may use this to Send an inquire.  r_buffer, r_length and
 * maxlen may all be NULL/0 to indicate that no real data is expected.
 * When this function returns, 
 *
 * Return value: 0 on success or an ASSUAN error code
 **/
gpg_error_t
assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen,
		    gpg_error_t (*cb) (void *cb_data, gpg_error_t rc,
				       unsigned char *buf, size_t len),
		    void *cb_data)
{
  gpg_error_t rc;
  struct membuf *mb = NULL;
  char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */

  if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  if (!ctx->is_server)
    return _assuan_error (ctx, GPG_ERR_ASS_NOT_A_SERVER);
  if (ctx->in_inquire)
    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);

  mb = malloc (sizeof (struct membuf));
  if (!mb)
    return _assuan_error (ctx, gpg_err_code_from_syserror ());
  init_membuf (ctx, mb, maxlen ? maxlen : 1024, maxlen);

  strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
  rc = assuan_write_line (ctx, cmdbuf);
  if (rc)
    {
      free_membuf (ctx, mb); 
      free (mb);
      return rc;
    }

  ctx->in_inquire = 1;

  /* Set up the continuation.  */
  ctx->inquire_cb = cb;
  ctx->inquire_cb_data = cb_data;
  ctx->inquire_membuf = mb;

  return 0;
}
示例#20
0
文件: server.c 项目: Juul/gnupg
/*  VERIFY

   This does a verify operation on the message send to the input-FD.
   The result is written out using status lines.  If an output FD was
   given, the signed text will be written to that.

   If the signature is a detached one, the server will inquire about
   the signed material and the client must provide it.
 */
static gpg_error_t
cmd_verify (assuan_context_t ctx, char *line)
{
  int rc;
  ctrl_t ctrl = assuan_get_pointer (ctx);
  gnupg_fd_t fd = assuan_get_input_fd (ctx);
  gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
  estream_t out_fp = NULL;

  /* FIXME: Revamp this code it is nearly to 3 years old and was only
     intended as a quick test.  */

  (void)line;

  if (fd == GNUPG_INVALID_FD)
    return gpg_error (GPG_ERR_ASS_NO_INPUT);

  if (out_fd != GNUPG_INVALID_FD)
    {
      out_fp = es_fdopen_nc (out_fd, "w");
      if (!out_fp)
        return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
    }

  log_debug ("WARNING: The server mode is WORK "
             "iN PROGRESS and not ready for use\n");

  rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);

  es_fclose (out_fp);
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);

  if (rc)
    log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
  return rc;
}
示例#21
0
/* Write out any buffered data
   This function is used for GNU's custom streams */
int
_assuan_cookie_write_flush (void *cookie)
{
  assuan_context_t ctx = cookie;
  char *line;
  size_t linelen;
  unsigned int monitor_result;

  if (ctx->outbound.data.error)
    return 0;

  line = ctx->outbound.data.line;
  linelen = ctx->outbound.data.linelen;
  line += linelen;

  monitor_result = 0;
  if (ctx->io_monitor)
    monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1,
				      ctx->outbound.data.line, linelen);

  if (linelen)
    {
      if (!(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
        _assuan_log_control_channel (ctx, 1, NULL,
                                     ctx->outbound.data.line, linelen,
                                     NULL, 0);
      *line++ = '\n';
      linelen++;
      if (! (monitor_result & ASSUAN_IO_MONITOR_IGNORE)
           && writen (ctx, ctx->outbound.data.line, linelen))
        {
          ctx->outbound.data.error = gpg_err_code_from_syserror ();
          return 0;
        }
      ctx->outbound.data.linelen = 0;
    }
  return 0;
}
示例#22
0
static gpg_error_t
cmd_genkey (assuan_context_t ctx, char *line)
{
  ctrl_t ctrl = assuan_get_pointer (ctx);
  int inp_fd, out_fd;
  estream_t in_stream, out_stream;
  int rc;

  (void)line;

  inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
  if (inp_fd == -1)
    return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
  out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
  if (out_fd == -1)
    return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);

  in_stream = es_fdopen_nc (inp_fd, "r");
  if (!in_stream)
    return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen failed");

  out_stream = es_fdopen_nc (out_fd, "w");
  if (!out_stream)
    {
      es_fclose (in_stream);
      return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
    }
  rc = gpgsm_genkey (ctrl, in_stream, out_stream);
  es_fclose (out_stream);
  es_fclose (in_stream);

  /* close and reset the fds */
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);

  return rc;
}
示例#23
0
/* Set the text used for the next OK reponse.  This string is
   automatically reset to NULL after the next command. */
gpg_error_t
assuan_set_okay_line (assuan_context_t ctx, const char *line)
{
  if (!ctx)
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  if (!line)
    {
      _assuan_free (ctx, ctx->okay_line);
      ctx->okay_line = NULL;
    }
  else
    {
      /* FIXME: we need to use gcry_is_secure() to test whether
         we should allocate the entire line in secure memory */
      char *buf = _assuan_malloc (ctx, 3 + strlen(line) + 1);
      if (!buf)
        return _assuan_error (ctx, gpg_err_code_from_syserror ());
      strcpy (buf, "OK ");
      strcpy (buf+3, line);
      _assuan_free (ctx, ctx->okay_line);
      ctx->okay_line = buf;
    }
  return 0;
}
示例#24
0
gcry_err_code_t
_gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
			    int algo, int mode, unsigned int flags)
{
  int secure = (flags & GCRY_CIPHER_SECURE);
  gcry_cipher_spec_t *spec;
  gcry_cipher_hd_t h = NULL;
  gcry_err_code_t err;

  /* If the application missed to call the random poll function, we do
     it here to ensure that it is used once in a while. */
  _gcry_fast_random_poll ();

  spec = spec_from_algo (algo);
  if (!spec)
    err = GPG_ERR_CIPHER_ALGO;
  else if (spec->flags.disabled)
    err = GPG_ERR_CIPHER_ALGO;
  else
    err = 0;

  /* check flags */
  if ((! err)
      && ((flags & ~(0
		     | GCRY_CIPHER_SECURE
		     | GCRY_CIPHER_ENABLE_SYNC
		     | GCRY_CIPHER_CBC_CTS
		     | GCRY_CIPHER_CBC_MAC))
	  || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
    err = GPG_ERR_CIPHER_ALGO;

  /* check that a valid mode has been requested */
  if (! err)
    switch (mode)
      {
      case GCRY_CIPHER_MODE_CCM:
#ifdef HAVE_U64_TYPEDEF
	if (spec->blocksize != GCRY_CCM_BLOCK_LEN)
	  err = GPG_ERR_INV_CIPHER_MODE;
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;
#else
        err = GPG_ERR_NOT_SUPPORTED;
#endif

      case GCRY_CIPHER_MODE_ECB:
      case GCRY_CIPHER_MODE_CBC:
      case GCRY_CIPHER_MODE_CFB:
      case GCRY_CIPHER_MODE_OFB:
      case GCRY_CIPHER_MODE_CTR:
      case GCRY_CIPHER_MODE_AESWRAP:
      case GCRY_CIPHER_MODE_CMAC:
      case GCRY_CIPHER_MODE_GCM:
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_POLY1305:
	if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv)
	  err = GPG_ERR_INV_CIPHER_MODE;
	else if (spec->algo != GCRY_CIPHER_CHACHA20)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_OCB:
        /* Note that our implementation allows only for 128 bit block
           length algorithms.  Lower block lengths would be possible
           but we do not implement them because they limit the
           security too much.  */
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	else if (spec->blocksize != (128/8))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_STREAM:
	if (!spec->stencrypt || !spec->stdecrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_NONE:
        /* This mode may be used for debugging.  It copies the main
           text verbatim to the ciphertext.  We do not allow this in
           fips mode or if no debug flag has been set.  */
	if (fips_mode () || !_gcry_get_debug_flag (0))
          err = GPG_ERR_INV_CIPHER_MODE;
	break;

      default:
	err = GPG_ERR_INV_CIPHER_MODE;
      }

  /* Perform selftest here and mark this with a flag in cipher_table?
     No, we should not do this as it takes too long.  Further it does
     not make sense to exclude algorithms with failing selftests at
     runtime: If a selftest fails there is something seriously wrong
     with the system and thus we better die immediately. */

  if (! err)
    {
      size_t size = (sizeof (*h)
                     + 2 * spec->contextsize
                     - sizeof (cipher_context_alignment_t)
#ifdef NEED_16BYTE_ALIGNED_CONTEXT
                     + 15  /* Space for leading alignment gap.  */
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
                     );

      if (secure)
	h = xtrycalloc_secure (1, size);
      else
	h = xtrycalloc (1, size);

      if (! h)
	err = gpg_err_code_from_syserror ();
      else
	{
          size_t off = 0;

#ifdef NEED_16BYTE_ALIGNED_CONTEXT
          if ( ((uintptr_t)h & 0x0f) )
            {
              /* The malloced block is not aligned on a 16 byte
                 boundary.  Correct for this.  */
              off = 16 - ((uintptr_t)h & 0x0f);
              h = (void*)((char*)h + off);
            }
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/

	  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
          h->actual_handle_size = size - off;
          h->handle_offset = off;
	  h->spec = spec;
          h->algo = algo;
	  h->mode = mode;
	  h->flags = flags;

          /* Setup bulk encryption routines.  */
          switch (algo)
            {
#ifdef USE_AES
            case GCRY_CIPHER_AES128:
            case GCRY_CIPHER_AES192:
            case GCRY_CIPHER_AES256:
              h->bulk.cfb_enc = _gcry_aes_cfb_enc;
              h->bulk.cfb_dec = _gcry_aes_cfb_dec;
              h->bulk.cbc_enc = _gcry_aes_cbc_enc;
              h->bulk.cbc_dec = _gcry_aes_cbc_dec;
              h->bulk.ctr_enc = _gcry_aes_ctr_enc;
              h->bulk.ocb_crypt = _gcry_aes_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_aes_ocb_auth;
              break;
#endif /*USE_AES*/
#ifdef USE_BLOWFISH
	    case GCRY_CIPHER_BLOWFISH:
              h->bulk.cfb_dec = _gcry_blowfish_cfb_dec;
              h->bulk.cbc_dec = _gcry_blowfish_cbc_dec;
              h->bulk.ctr_enc = _gcry_blowfish_ctr_enc;
              break;
#endif /*USE_BLOWFISH*/
#ifdef USE_CAST5
	    case GCRY_CIPHER_CAST5:
              h->bulk.cfb_dec = _gcry_cast5_cfb_dec;
              h->bulk.cbc_dec = _gcry_cast5_cbc_dec;
              h->bulk.ctr_enc = _gcry_cast5_ctr_enc;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_CAMELLIA
	    case GCRY_CIPHER_CAMELLIA128:
	    case GCRY_CIPHER_CAMELLIA192:
	    case GCRY_CIPHER_CAMELLIA256:
              h->bulk.cbc_dec = _gcry_camellia_cbc_dec;
              h->bulk.cfb_dec = _gcry_camellia_cfb_dec;
              h->bulk.ctr_enc = _gcry_camellia_ctr_enc;
              h->bulk.ocb_crypt = _gcry_camellia_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_camellia_ocb_auth;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_DES
            case GCRY_CIPHER_3DES:
              h->bulk.cbc_dec =  _gcry_3des_cbc_dec;
              h->bulk.cfb_dec =  _gcry_3des_cfb_dec;
              h->bulk.ctr_enc =  _gcry_3des_ctr_enc;
              break;
#endif /*USE_DES*/
#ifdef USE_SERPENT
	    case GCRY_CIPHER_SERPENT128:
	    case GCRY_CIPHER_SERPENT192:
	    case GCRY_CIPHER_SERPENT256:
              h->bulk.cbc_dec = _gcry_serpent_cbc_dec;
              h->bulk.cfb_dec = _gcry_serpent_cfb_dec;
              h->bulk.ctr_enc = _gcry_serpent_ctr_enc;
              h->bulk.ocb_crypt = _gcry_serpent_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_serpent_ocb_auth;
              break;
#endif /*USE_SERPENT*/
#ifdef USE_TWOFISH
	    case GCRY_CIPHER_TWOFISH:
	    case GCRY_CIPHER_TWOFISH128:
              h->bulk.cbc_dec = _gcry_twofish_cbc_dec;
              h->bulk.cfb_dec = _gcry_twofish_cfb_dec;
              h->bulk.ctr_enc = _gcry_twofish_ctr_enc;
              h->bulk.ocb_crypt = _gcry_twofish_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_twofish_ocb_auth;
              break;
#endif /*USE_TWOFISH*/

            default:
              break;
            }

          /* Setup defaults depending on the mode.  */
          switch (mode)
            {
            case GCRY_CIPHER_MODE_OCB:
              h->u_mode.ocb.taglen = 16; /* Bytes.  */
              break;

            default:
              break;
            }

	}
    }

  /* Done.  */

  *handle = err ? NULL : h;

  return err;
}
示例#25
0
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     gpg_err_source_t errsource,
                     void (*preexec)(void), unsigned int flags,
                     estream_t infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
  gpg_error_t err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi =
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  STARTUPINFO si;
  int cr_flags;
  char *cmdline;
  HANDLE inhandle = INVALID_HANDLE_VALUE;
  HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  estream_t outfp = NULL;
  estream_t errfp = NULL;
  HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
                      INVALID_HANDLE_VALUE,
                      INVALID_HANDLE_VALUE};
  int i;
  es_syshd_t syshd;

  if (r_outfp)
    *r_outfp = NULL;
  if (r_errfp)
    *r_errfp = NULL;
  *pid = (pid_t)(-1); /* Always required.  */

  if (infp)
    {
      es_fflush (infp);
      es_rewind (infp);
      es_syshd (infp, &syshd);
      switch (syshd.type)
        {
        case ES_SYSHD_FD:
          inhandle = (HANDLE)_get_osfhandle (syshd.u.fd);
          break;
        case ES_SYSHD_SOCK:
          inhandle = (HANDLE)_get_osfhandle (syshd.u.sock);
          break;
        case ES_SYSHD_HANDLE:
          inhandle = syshd.u.handle;
          break;
        default:
          inhandle = INVALID_HANDLE_VALUE;
          break;
        }
      if (inhandle == INVALID_HANDLE_VALUE)
        return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
      /* FIXME: In case we can't get a system handle (e.g. due to
         es_fopencookie we should create a piper and a feeder
         thread.  */
    }

  if (r_outfp)
    {
      if (create_inheritable_pipe (outpipe, 1))
        {
          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
          return err;
        }

      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = outpipe[0];
      outfp = es_sysopen (&syshd, "r");
      if (!outfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error (_("error creating a stream for a pipe: %s\n"),
                     gpg_strerror (err));
          CloseHandle (outpipe[0]);
          CloseHandle (outpipe[1]);
          outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
          return err;
        }
    }

  if (r_errfp)
    {
      if (create_inheritable_pipe (errpipe, 1))
        {
          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
          return err;
        }

      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = errpipe[0];
      errfp = es_sysopen (&syshd, "r");
      if (!errfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error (_("error creating a stream for a pipe: %s\n"),
                     gpg_strerror (err));
          CloseHandle (errpipe[0]);
          CloseHandle (errpipe[1]);
          errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
          if (outfp)
            es_fclose (outfp);
          else if (outpipe[0] != INVALID_HANDLE_VALUE)
            CloseHandle (outpipe[0]);
          if (outpipe[1] != INVALID_HANDLE_VALUE)
            CloseHandle (outpipe[1]);
          return err;
        }
    }

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr );
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;

  /* Build the command line.  */
  err = build_w32_commandline (pgmname, argv, &cmdline);
  if (err)
    return err;

  if (inhandle != INVALID_HANDLE_VALUE)
    nullhd[0] = w32_open_null (0);
  if (outpipe[1] != INVALID_HANDLE_VALUE)
    nullhd[1] = w32_open_null (0);
  if (errpipe[1] != INVALID_HANDLE_VALUE)
    nullhd[2] = w32_open_null (0);

  /* Start the process.  Note that we can't run the PREEXEC function
     because this might change our own environment. */
  (void)preexec;

  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
  si.hStdInput  =   inhandle == INVALID_HANDLE_VALUE? nullhd[0] : inhandle;
  si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
  si.hStdError  = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];

  cr_flags = (CREATE_DEFAULT_ERROR_MODE
              | ((flags & 128)? DETACHED_PROCESS : 0)
              | GetPriorityClass (GetCurrentProcess ())
              | CREATE_SUSPENDED);
/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      cr_flags,      /* Creation flags.  */
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      if (outfp)
        es_fclose (outfp);
      else if (outpipe[0] != INVALID_HANDLE_VALUE)
        CloseHandle (outpipe[0]);
      if (outpipe[1] != INVALID_HANDLE_VALUE)
        CloseHandle (outpipe[1]);
      if (errfp)
        es_fclose (errfp);
      else if (errpipe[0] != INVALID_HANDLE_VALUE)
        CloseHandle (errpipe[0]);
      if (errpipe[1] != INVALID_HANDLE_VALUE)
        CloseHandle (errpipe[1]);
      return gpg_err_make (errsource, GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

  /* Close the inherited handles to /dev/null.  */
  for (i=0; i < DIM (nullhd); i++)
    if (nullhd[i] != INVALID_HANDLE_VALUE)
      CloseHandle (nullhd[i]);

  /* Close the inherited ends of the pipes.  */
  if (outpipe[1] != INVALID_HANDLE_VALUE)
    CloseHandle (outpipe[1]);
  if (errpipe[1] != INVALID_HANDLE_VALUE)
    CloseHandle (errpipe[1]);

  /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
  /*            " dwProcessID=%d dwThreadId=%d\n", */
  /*            pi.hProcess, pi.hThread, */
  /*            (int) pi.dwProcessId, (int) pi.dwThreadId); */
  /* log_debug ("                     outfp=%p errfp=%p\n", outfp, errfp); */

  /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
     invalid argument error if we pass it the correct processID.  As a
     workaround we use -1 (ASFW_ANY).  */
  if ( (flags & 64) )
    gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  if (r_outfp)
    *r_outfp = outfp;
  if (r_errfp)
    *r_errfp = errfp;

  *pid = handle_to_pid (pi.hProcess);
  return 0;

}
示例#26
0
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     gpg_err_source_t errsource,
                     void (*preexec)(void), unsigned int flags,
                     estream_t infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
    gpg_error_t err;
    int infd = -1;
    int outpipe[2] = {-1, -1};
    int errpipe[2] = {-1, -1};
    estream_t outfp = NULL;
    estream_t errfp = NULL;

    (void)flags; /* Currently not used.  */

    if (r_outfp)
        *r_outfp = NULL;
    if (r_errfp)
        *r_errfp = NULL;
    *pid = (pid_t)(-1); /* Always required.  */

    if (infp)
    {
        es_fflush (infp);
        es_rewind (infp);
        infd = es_fileno (infp);
        if (infd == -1)
            return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
    }

    if (r_outfp)
    {
        err = create_pipe_and_estream (outpipe, &outfp, errsource);
        if (err)
            return err;
    }

    if (r_errfp)
    {
        err = create_pipe_and_estream (errpipe, &errfp, errsource);
        if (err)
        {
            if (outfp)
                es_fclose (outfp);
            else if (outpipe[0] != -1)
                close (outpipe[0]);
            if (outpipe[1] != -1)
                close (outpipe[1]);
            return err;
        }
    }


    *pid = fork ();
    if (*pid == (pid_t)(-1))
    {
        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
        log_error (_("error forking process: %s\n"), gpg_strerror (err));

        if (outfp)
            es_fclose (outfp);
        else if (outpipe[0] != -1)
            close (outpipe[0]);
        if (outpipe[1] != -1)
            close (outpipe[1]);

        if (errfp)
            es_fclose (errfp);
        else if (errpipe[0] != -1)
            close (errpipe[0]);
        if (errpipe[1] != -1)
            close (errpipe[1]);
        return err;
    }

    if (!*pid)
    {
        /* This is the child. */
        gcry_control (GCRYCTL_TERM_SECMEM);
        es_fclose (outfp);
        es_fclose (errfp);
        do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
        /*NOTREACHED*/
    }

    /* This is the parent. */
    if (outpipe[1] != -1)
        close (outpipe[1]);
    if (errpipe[1] != -1)
        close (errpipe[1]);

    if (r_outfp)
        *r_outfp = outfp;
    if (r_errfp)
        *r_errfp = errfp;

    return 0;
}
示例#27
0
/* Read a line with buffering of partial lines.  Function returns an
   Assuan error.  */
gpg_error_t
_assuan_read_line (assuan_context_t ctx)
{
  gpg_error_t rc = 0;
  char *line = ctx->inbound.line;
  int nread, atticlen;
  char *endp = 0;

  if (ctx->inbound.eof)
    return _assuan_error (ctx, GPG_ERR_EOF);

  atticlen = ctx->inbound.attic.linelen;
  if (atticlen)
    {
      memcpy (line, ctx->inbound.attic.line, atticlen);
      ctx->inbound.attic.linelen = 0;

      endp = memchr (line, '\n', atticlen);
      if (endp)
	{
	  /* Found another line in the attic.  */
	  nread = atticlen;
	  atticlen = 0;
	}
      else
        {
	  /* There is pending data but not a full line.  */
          assert (atticlen < LINELENGTH);
          rc = readline (ctx, line + atticlen,
			 LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
        }
    }
  else
    /* No pending data.  */
    rc = readline (ctx, line, LINELENGTH,
                   &nread, &ctx->inbound.eof);
  if (rc)
    {
      int saved_errno = errno;
      char buf[100];

      snprintf (buf, sizeof buf, "error: %s", strerror (errno));
      _assuan_log_control_channel (ctx, 0, buf, NULL, 0, NULL, 0);

      if (saved_errno == EAGAIN)
        {
          /* We have to save a partial line.  Due to readline's
	     behaviour, we know that this is not a complete line yet
	     (no newline).  So we don't set PENDING to true.  */
          memcpy (ctx->inbound.attic.line, line, atticlen + nread);
          ctx->inbound.attic.pending = 0;
          ctx->inbound.attic.linelen = atticlen + nread;
        }

      gpg_err_set_errno (saved_errno);
      return _assuan_error (ctx, gpg_err_code_from_syserror ());
    }
  if (!nread)
    {
      assert (ctx->inbound.eof);
      _assuan_log_control_channel (ctx, 0, "eof", NULL, 0, NULL, 0);
      return _assuan_error (ctx, GPG_ERR_EOF);
    }

  ctx->inbound.attic.pending = 0;
  nread += atticlen;

  if (! endp)
    endp = memchr (line, '\n', nread);

  if (endp)
    {
      unsigned monitor_result;
      int n = endp - line + 1;

      if (n < nread)
	/* LINE contains more than one line.  We copy it to the attic
	   now as handlers are allowed to modify the passed
	   buffer.  */
	{
	  int len = nread - n;
	  memcpy (ctx->inbound.attic.line, endp + 1, len);
	  ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
	  ctx->inbound.attic.linelen = len;
	}

      if (endp != line && endp[-1] == '\r')
	endp --;
      *endp = 0;

      ctx->inbound.linelen = endp - line;

      monitor_result = 0;
      if (ctx->io_monitor)
	monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 0,
					  ctx->inbound.line,
					  ctx->inbound.linelen);
      if (monitor_result & ASSUAN_IO_MONITOR_IGNORE)
        ctx->inbound.linelen = 0;

      if ( !(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
        _assuan_log_control_channel (ctx, 0, NULL,
                                     ctx->inbound.line, ctx->inbound.linelen,
                                     NULL, 0);
      return 0;
    }
  else
    {
      _assuan_log_control_channel (ctx, 0, "invalid line",
                                   NULL, 0, NULL, 0);
      *line = 0;
      ctx->inbound.linelen = 0;
      return _assuan_error (ctx, ctx->inbound.eof
			    ? GPG_ERR_ASS_INCOMPLETE_LINE
			    : GPG_ERR_ASS_LINE_TOO_LONG);
    }
}
示例#28
0
/* Take the hash value and convert into an MPI, suitable for
   passing to the low level functions.  We currently support the
   old style way of passing just a MPI and the modern interface which
   allows to pass flags so that we can choose between raw and pkcs1
   padding - may be more padding options later.

   (<mpi>)
   or
   (data
    [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
    [(hash <algo> <value>)]
    [(value <text>)]
    [(hash-algo <algo>)]
    [(label <label>)]
    [(salt-length <length>)]
    [(random-override <data>)]
   )

   Either the VALUE or the HASH element must be present for use
   with signatures.  VALUE is used for encryption.

   HASH-ALGO is specific to OAEP and EDDSA.

   LABEL is specific to OAEP.

   SALT-LENGTH is for PSS.

   RANDOM-OVERRIDE is used to replace random nonces for regression
   testing.  */
gcry_err_code_t
_gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                           struct pk_encoding_ctx *ctx)
{
  gcry_err_code_t rc = 0;
  gcry_sexp_t ldata, lhash, lvalue;
  size_t n;
  const char *s;
  int unknown_flag = 0;
  int parsed_flags = 0;

  *ret_mpi = NULL;
  ldata = sexp_find_token (input, "data", 0);
  if (!ldata)
    { /* assume old style */
      *ret_mpi = sexp_nth_mpi (input, 0, 0);
      return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
    }

  /* See whether there is a flags list.  */
  {
    gcry_sexp_t lflags = sexp_find_token (ldata, "flags", 0);
    if (lflags)
      {
        if (_gcry_pk_util_parse_flaglist (lflags,
                                          &parsed_flags, &ctx->encoding))
          unknown_flag = 1;
        sexp_release (lflags);
      }
  }

  if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
    ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */

  /* Get HASH or MPI */
  lhash = sexp_find_token (ldata, "hash", 0);
  lvalue = lhash? NULL : sexp_find_token (ldata, "value", 0);

  if (!(!lhash ^ !lvalue))
    rc = GPG_ERR_INV_OBJ; /* none or both given */
  else if (unknown_flag)
    rc = GPG_ERR_INV_FLAG;
  else if (ctx->encoding == PUBKEY_ENC_RAW
           && (parsed_flags & PUBKEY_FLAG_EDDSA))
    {
      /* Prepare for EdDSA.  */
      gcry_sexp_t list;
      void *value;
      size_t valuelen;

      if (!lvalue)
        {
          rc = GPG_ERR_INV_OBJ;
          goto leave;
        }
      /* Get HASH-ALGO. */
      list = sexp_find_token (ldata, "hash-algo", 0);
      if (list)
        {
          s = sexp_nth_data (list, 1, &n);
          if (!s)
            rc = GPG_ERR_NO_OBJ;
          else
            {
              ctx->hash_algo = get_hash_algo (s, n);
              if (!ctx->hash_algo)
                rc = GPG_ERR_DIGEST_ALGO;
            }
          sexp_release (list);
        }
      else
        rc = GPG_ERR_INV_OBJ;
      if (rc)
        goto leave;

      /* Get VALUE.  */
      value = sexp_nth_buffer (lvalue, 1, &valuelen);
      if (!value)
        {
          /* We assume that a zero length message is meant by
             "(value)".  This is commonly used by test vectors.  Note
             that S-expression do not allow zero length items. */
          valuelen = 0;
          value = xtrymalloc (1);
          if (!value)
            rc = gpg_err_code_from_syserror ();
        }
      else if ((valuelen * 8) < valuelen)
        {
          xfree (value);
          rc = GPG_ERR_TOO_LARGE;
        }
      if (rc)
        goto leave;

      /* Note that mpi_set_opaque takes ownership of VALUE.  */
      *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
    }
  else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
           && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
               || (parsed_flags & PUBKEY_FLAG_RFC6979)))
    {
      /* Raw encoding along with a hash element.  This is commonly
         used for DSA.  For better backward error compatibility we
         allow this only if either the rfc6979 flag has been given or
         the raw flags was explicitly given.  */
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          void *value;
          size_t valuelen;

	  ctx->hash_algo = get_hash_algo (s, n);
          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
          else if (!(value=sexp_nth_buffer (lhash, 2, &valuelen)))
            rc = GPG_ERR_INV_OBJ;
          else if ((valuelen * 8) < valuelen)
            {
              xfree (value);
              rc = GPG_ERR_TOO_LARGE;
            }
          else
            *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
    {
      /* RFC6969 may only be used with the a hash value and not the
         MPI based value.  */
      if (parsed_flags & PUBKEY_FLAG_RFC6979)
        {
          rc = GPG_ERR_CONFLICT;
          goto leave;
        }

      /* Get the value */
      *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
      if (!*ret_mpi)
        rc = GPG_ERR_INV_OBJ;
    }
  else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue
	   && ctx->op == PUBKEY_OP_ENCRYPT)
    {
      const void * value;
      size_t valuelen;
      gcry_sexp_t list;
      void *random_override = NULL;
      size_t random_override_len = 0;

      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          /* Get optional RANDOM-OVERRIDE.  */
          list = sexp_find_token (ldata, "random-override", 0);
          if (list)
            {
              s = sexp_nth_data (list, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else if (n > 0)
                {
                  random_override = xtrymalloc (n);
                  if (!random_override)
                    rc = gpg_err_code_from_syserror ();
                  else
                    {
                      memcpy (random_override, s, n);
                      random_override_len = n;
                    }
                }
              sexp_release (list);
              if (rc)
                goto leave;
            }

          rc = _gcry_rsa_pkcs1_encode_for_enc (ret_mpi, ctx->nbits,
                                               value, valuelen,
                                               random_override,
                                               random_override_len);
          xfree (random_override);
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
	   && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
    {
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          const void * value;
          size_t valuelen;

	  ctx->hash_algo = get_hash_algo (s, n);

          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
                    || !valuelen )
            rc = GPG_ERR_INV_OBJ;
          else
	    rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
                                                 value, valuelen,
                                                 ctx->hash_algo);
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
	   && ctx->op == PUBKEY_OP_ENCRYPT)
    {
      const void * value;
      size_t valuelen;

      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
	rc = GPG_ERR_INV_OBJ;
      else
	{
	  gcry_sexp_t list;
          void *random_override = NULL;
          size_t random_override_len = 0;

	  /* Get HASH-ALGO. */
	  list = sexp_find_token (ldata, "hash-algo", 0);
	  if (list)
	    {
	      s = sexp_nth_data (list, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else
		{
		  ctx->hash_algo = get_hash_algo (s, n);
		  if (!ctx->hash_algo)
		    rc = GPG_ERR_DIGEST_ALGO;
		}
	      sexp_release (list);
	      if (rc)
		goto leave;
	    }

	  /* Get LABEL. */
	  list = sexp_find_token (ldata, "label", 0);
	  if (list)
	    {
	      s = sexp_nth_data (list, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else if (n > 0)
		{
		  ctx->label = xtrymalloc (n);
		  if (!ctx->label)
		    rc = gpg_err_code_from_syserror ();
		  else
		    {
		      memcpy (ctx->label, s, n);
		      ctx->labellen = n;
		    }
		}
	      sexp_release (list);
	      if (rc)
		goto leave;
	    }
          /* Get optional RANDOM-OVERRIDE.  */
          list = sexp_find_token (ldata, "random-override", 0);
          if (list)
            {
              s = sexp_nth_data (list, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else if (n > 0)
                {
                  random_override = xtrymalloc (n);
                  if (!random_override)
                    rc = gpg_err_code_from_syserror ();
                  else
                    {
                      memcpy (random_override, s, n);
                      random_override_len = n;
                    }
                }
              sexp_release (list);
              if (rc)
                goto leave;
            }

	  rc = _gcry_rsa_oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo,
                                      value, valuelen,
                                      ctx->label, ctx->labellen,
                                      random_override, random_override_len);

          xfree (random_override);
	}
    }
  else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
	   && ctx->op == PUBKEY_OP_SIGN)
    {
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          const void * value;
          size_t valuelen;
          void *random_override = NULL;
          size_t random_override_len = 0;

	  ctx->hash_algo = get_hash_algo (s, n);

          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
                    || !valuelen )
            rc = GPG_ERR_INV_OBJ;
          else
	    {
	      gcry_sexp_t list;

	      /* Get SALT-LENGTH. */
	      list = sexp_find_token (ldata, "salt-length", 0);
	      if (list)
		{
		  s = sexp_nth_data (list, 1, &n);
		  if (!s)
		    {
		      rc = GPG_ERR_NO_OBJ;
		      goto leave;
		    }
		  ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
		  sexp_release (list);
		}

              /* Get optional RANDOM-OVERRIDE.  */
              list = sexp_find_token (ldata, "random-override", 0);
              if (list)
                {
                  s = sexp_nth_data (list, 1, &n);
                  if (!s)
                    rc = GPG_ERR_NO_OBJ;
                  else if (n > 0)
                    {
                      random_override = xtrymalloc (n);
                      if (!random_override)
                        rc = gpg_err_code_from_syserror ();
                      else
                        {
                          memcpy (random_override, s, n);
                          random_override_len = n;
                        }
                    }
                  sexp_release (list);
                  if (rc)
                    goto leave;
                }

              /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
	      rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
                                         ctx->hash_algo,
                                         value, valuelen, ctx->saltlen,
                                         random_override, random_override_len);

              xfree (random_override);
	    }
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
	   && ctx->op == PUBKEY_OP_VERIFY)
    {
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
	  ctx->hash_algo = get_hash_algo (s, n);

          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
	  else
	    {
	      *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
	      if (!*ret_mpi)
		rc = GPG_ERR_INV_OBJ;
	      ctx->verify_cmp = pss_verify_cmp;
	      ctx->verify_arg = *ret_mpi;
	    }
	}
    }
  else
    rc = GPG_ERR_CONFLICT;

 leave:
  sexp_release (ldata);
  sexp_release (lhash);
  sexp_release (lvalue);

  if (!rc)
    ctx->flags = parsed_flags;
  else
    {
      xfree (ctx->label);
      ctx->label = NULL;
    }

  return rc;
}
示例#29
0
/* Parse a "enc-val" s-expression and store the inner parameter list
   at R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
   "enc-val" is valid.  Returns 0 on success and stores a new list at
   R_PARMS which must be freed by the caller.  On error R_PARMS is set
   to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
   values are set into it; as of now they are only used with ecc
   algorithms.

     (enc-val
       [(flags [raw, pkcs1, oaep, no-blinding])]
       [(hash-algo <algo>)]
       [(label <label>)]
        (<algo>
          (<param_name1> <mpi>)
          ...
          (<param_namen> <mpi>)))

   HASH-ALGO and LABEL are specific to OAEP.  CTX will be updated with
   encoding information.  */
gpg_err_code_t
_gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
                               gcry_sexp_t *r_parms,
                               struct pk_encoding_ctx *ctx)
{
  gcry_err_code_t rc = 0;
  gcry_sexp_t l1 = NULL;
  gcry_sexp_t l2 = NULL;
  char *name = NULL;
  size_t n;
  int parsed_flags = 0;
  int i;

  *r_parms = NULL;

  /* Check that the first element is valid.  */
  l1 = sexp_find_token (sexp, "enc-val" , 0);
  if (!l1)
    {
      rc = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object.  */
      goto leave;
    }

  l2 = sexp_nth (l1, 1);
  if (!l2)
    {
      rc = GPG_ERR_NO_OBJ;  /* No cadr for the data object.  */
      goto leave;
    }

  /* Extract identifier of sublist.  */
  name = sexp_nth_string (l2, 0);
  if (!name)
    {
      rc = GPG_ERR_INV_OBJ; /* Invalid structure of object.  */
      goto leave;
    }

  if (!strcmp (name, "flags"))
    {
      const char *s;

      /* There is a flags element - process it.  */
      rc = _gcry_pk_util_parse_flaglist (l2, &parsed_flags, &ctx->encoding);
      if (rc)
        goto leave;
      if (ctx->encoding == PUBKEY_ENC_PSS)
        {
          rc = GPG_ERR_CONFLICT;
          goto leave;
        }

      /* Get the OAEP parameters HASH-ALGO and LABEL, if any. */
      if (ctx->encoding == PUBKEY_ENC_OAEP)
	{
	  /* Get HASH-ALGO. */
          sexp_release (l2);
	  l2 = sexp_find_token (l1, "hash-algo", 0);
	  if (l2)
	    {
	      s = sexp_nth_data (l2, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else
		{
		  ctx->hash_algo = get_hash_algo (s, n);
		  if (!ctx->hash_algo)
		    rc = GPG_ERR_DIGEST_ALGO;
		}
	      if (rc)
		goto leave;
	    }

	  /* Get LABEL. */
          sexp_release (l2);
	  l2 = sexp_find_token (l1, "label", 0);
	  if (l2)
	    {
	      s = sexp_nth_data (l2, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else if (n > 0)
		{
		  ctx->label = xtrymalloc (n);
		  if (!ctx->label)
		    rc = gpg_err_code_from_syserror ();
		  else
		    {
		      memcpy (ctx->label, s, n);
		      ctx->labellen = n;
		    }
		}
	      if (rc)
		goto leave;
	    }
	}

      /* Get the next which has the actual data - skip HASH-ALGO and LABEL. */
      for (i = 2; (sexp_release (l2), l2 = sexp_nth (l1, i)); i++)
	{
	  s = sexp_nth_data (l2, 0, &n);
	  if (!(n == 9 && !memcmp (s, "hash-algo", 9))
	      && !(n == 5 && !memcmp (s, "label", 5))
	      && !(n == 15 && !memcmp (s, "random-override", 15)))
	    break;
	}
      if (!l2)
        {
          rc = GPG_ERR_NO_OBJ; /* No cadr for the data object. */
          goto leave;
        }

      /* Extract sublist identifier.  */
      xfree (name);
      name = sexp_nth_string (l2, 0);
      if (!name)
        {
          rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
          goto leave;
        }
    }
  else /* No flags - flag as legacy structure.  */
    parsed_flags |= PUBKEY_FLAG_LEGACYRESULT;

  for (i=0; algo_names[i]; i++)
    if (!stricmp (name, algo_names[i]))
      break;
  if (!algo_names[i])
    {
      rc = GPG_ERR_CONFLICT; /* "enc-val" uses an unexpected algo. */
      goto leave;
    }

  *r_parms = l2;
  l2 = NULL;
  ctx->flags |= parsed_flags;
  rc = 0;

 leave:
  xfree (name);
  sexp_release (l2);
  sexp_release (l1);
  return rc;
}
示例#30
0
/* Write out the data in buffer as datalines with line wrapping and
   percent escaping.  This function is used for GNU's custom streams. */
int
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
{
  assuan_context_t ctx = cookie;
  size_t size = orig_size;
  char *line;
  size_t linelen;

  if (ctx->outbound.data.error)
    return 0;

  line = ctx->outbound.data.line;
  linelen = ctx->outbound.data.linelen;
  line += linelen;
  while (size)
    {
      unsigned int monitor_result;

      /* Insert data line header. */
      if (!linelen)
        {
          *line++ = 'D';
          *line++ = ' ';
          linelen += 2;
        }

      /* Copy data, keep space for the CRLF and to escape one character. */
      while (size && linelen < LINELENGTH-2-2)
        {
          if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
            {
              sprintf (line, "%%%02X", *(unsigned char*)buffer);
              line += 3;
              linelen += 3;
              buffer++;
            }
          else
            {
              *line++ = *buffer++;
              linelen++;
            }
          size--;
        }


      monitor_result = 0;
      if (ctx->io_monitor)
	monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1,
					  ctx->outbound.data.line, linelen);

      if (linelen >= LINELENGTH-2-2)
        {
          if (!(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
            _assuan_log_control_channel (ctx, 1, NULL,
                                         ctx->outbound.data.line, linelen,
                                         NULL, 0);

          *line++ = '\n';
          linelen++;
          if ( !(monitor_result & ASSUAN_IO_MONITOR_IGNORE)
               && writen (ctx, ctx->outbound.data.line, linelen))
            {
              ctx->outbound.data.error = gpg_err_code_from_syserror ();
              return 0;
            }
          line = ctx->outbound.data.line;
          linelen = 0;
        }
    }

  ctx->outbound.data.linelen = linelen;
  return (int) orig_size;
}