Blame src/sign.c

Packit Service 672cf4
/* sign.c - Signing function.
Packit Service 6c01f9
   Copyright (C) 2000 Werner Koch (dd9jn)
Packit Service 6c01f9
   Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
Packit Service 6c01f9
Packit Service 6c01f9
   This file is part of GPGME.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is free software; you can redistribute it and/or modify it
Packit Service 6c01f9
   under the terms of the GNU Lesser General Public License as
Packit Service 6c01f9
   published by the Free Software Foundation; either version 2.1 of
Packit Service 6c01f9
   the License, or (at your option) any later version.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is distributed in the hope that it will be useful, but
Packit Service 6c01f9
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 6c01f9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 6c01f9
   Lesser General Public License for more details.
Packit Service 6c01f9
Packit Service 6c01f9
   You should have received a copy of the GNU Lesser General Public
Packit Service 6c01f9
   License along with this program; if not, write to the Free Software
Packit Service 6c01f9
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
Packit Service 6c01f9
   02111-1307, USA.  */
Packit Service 672cf4
Packit Service 672cf4
#if HAVE_CONFIG_H
Packit Service 672cf4
#include <config.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#include <stdlib.h>
Packit Service 672cf4
#include <string.h>
Packit Service 672cf4
#include <errno.h>
Packit Service 672cf4
Packit Service 672cf4
/* Suppress warning for accessing deprecated member "class".  */
Packit Service 672cf4
#define _GPGME_IN_GPGME 1
Packit Service 672cf4
#include "gpgme.h"
Packit Service 672cf4
#include "context.h"
Packit Service 672cf4
#include "ops.h"
Packit Service 672cf4
#include "util.h"
Packit Service 672cf4
#include "debug.h"
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
typedef struct
Packit Service 672cf4
{
Packit Service 672cf4
  struct _gpgme_op_sign_result result;
Packit Service 672cf4
Packit Service 672cf4
  /* The error code from a FAILURE status line or 0.  */
Packit Service 672cf4
  gpg_error_t failure_code;
Packit Service 672cf4
Packit Service 672cf4
  /* The fingerprint from the last KEY_CONSIDERED status line.  */
Packit Service 672cf4
  char *kc_fpr;
Packit Service 672cf4
Packit Service 672cf4
  /* The flags from the last KEY_CONSIDERED status line.  */
Packit Service 672cf4
  unsigned int kc_flags;
Packit Service 672cf4
Packit Service 672cf4
  /* A pointer to the next pointer of the last invalid signer in
Packit Service 672cf4
     the list.  This makes appending new invalid signers painless
Packit Service 672cf4
     while preserving the order.  */
Packit Service 672cf4
  gpgme_invalid_key_t *last_signer_p;
Packit Service 672cf4
Packit Service 672cf4
  /* Likewise for signature information.  */
Packit Service 672cf4
  gpgme_new_signature_t *last_sig_p;
Packit Service 672cf4
Packit Service 672cf4
  /* Flags used while processing the status lines.  */
Packit Service 672cf4
  unsigned int ignore_inv_recp:1;
Packit Service 672cf4
  unsigned int inv_sgnr_seen:1;
Packit Service 672cf4
  unsigned int sig_created_seen:1;
Packit Service 672cf4
} *op_data_t;
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static void
Packit Service 672cf4
release_signatures (gpgme_new_signature_t sig)
Packit Service 672cf4
{
Packit Service 672cf4
  while (sig)
Packit Service 672cf4
    {
Packit Service 672cf4
      gpgme_new_signature_t next = sig->next;
Packit Service 672cf4
      free (sig->fpr);
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      sig = next;
Packit Service 672cf4
    }
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static void
Packit Service 672cf4
release_op_data (void *hook)
Packit Service 672cf4
{
Packit Service 672cf4
  op_data_t opd = (op_data_t) hook;
Packit Service 672cf4
  gpgme_invalid_key_t invalid_signer = opd->result.invalid_signers;
Packit Service 672cf4
Packit Service 672cf4
  while (invalid_signer)
Packit Service 672cf4
    {
Packit Service 672cf4
      gpgme_invalid_key_t next = invalid_signer->next;
Packit Service 672cf4
      if (invalid_signer->fpr)
Packit Service 672cf4
	free (invalid_signer->fpr);
Packit Service 672cf4
      free (invalid_signer);
Packit Service 672cf4
      invalid_signer = next;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  release_signatures (opd->result.signatures);
Packit Service 672cf4
  free (opd->kc_fpr);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
gpgme_sign_result_t
Packit Service 672cf4
gpgme_op_sign_result (gpgme_ctx_t ctx)
Packit Service 672cf4
{
Packit Service 672cf4
  void *hook;
Packit Service 672cf4
  op_data_t opd;
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  gpgme_invalid_key_t inv_key, key;
Packit Service 672cf4
  gpgme_new_signature_t sig;
Packit Service 672cf4
  unsigned int inv_signers = 0;
Packit Service 672cf4
  unsigned int signatures = 0;
Packit Service 672cf4
Packit Service 6c01f9
  TRACE_BEG (DEBUG_CTX, "gpgme_op_sign_result", ctx);
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
Packit Service 672cf4
  opd = hook;
Packit Service 672cf4
  if (err || !opd)
Packit Service 672cf4
    {
Packit Service 6c01f9
      TRACE_SUC0 ("result=(null)");
Packit Service 672cf4
      return NULL;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  for (inv_key = opd->result.invalid_signers; inv_key; inv_key = inv_key->next)
Packit Service 672cf4
    inv_signers++;
Packit Service 672cf4
  for (sig = opd->result.signatures; sig; sig = sig->next)
Packit Service 672cf4
    signatures++;
Packit Service 672cf4
Packit Service 672cf4
  if (gpgme_signers_count (ctx)
Packit Service 672cf4
      && signatures + inv_signers != gpgme_signers_count (ctx))
Packit Service 672cf4
    {
Packit Service 672cf4
      /* In this case at least one signatures was not created perhaps
Packit Service 672cf4
         due to a bad passphrase etc.  Thus the entire message is
Packit Service 672cf4
         broken and should not be used.  We add the already created
Packit Service 672cf4
         signatures to the invalid signers list and thus this case can
Packit Service 672cf4
         be detected.  */
Packit Service 6c01f9
      TRACE_LOG3 ("result: invalid signers: %u, signatures: %u, count: %u",
Packit Service 672cf4
                  inv_signers, signatures, gpgme_signers_count (ctx));
Packit Service 672cf4
Packit Service 672cf4
      for (sig = opd->result.signatures; sig; sig = sig->next)
Packit Service 672cf4
        {
Packit Service 672cf4
          key = calloc (1, sizeof *key);
Packit Service 672cf4
          if (!key)
Packit Service 672cf4
            {
Packit Service 6c01f9
              TRACE_SUC0 ("out of core; result=(null)");
Packit Service 672cf4
              return NULL;
Packit Service 672cf4
            }
Packit Service 672cf4
          if (sig->fpr)
Packit Service 672cf4
            {
Packit Service 672cf4
              key->fpr = strdup (sig->fpr);
Packit Service 672cf4
              if (!key->fpr)
Packit Service 672cf4
                {
Packit Service 672cf4
                  free (key);
Packit Service 6c01f9
                  TRACE_SUC0 ("out of core; result=(null)");
Packit Service 672cf4
                  return NULL;
Packit Service 672cf4
                }
Packit Service 672cf4
            }
Packit Service 672cf4
          key->reason = GPG_ERR_GENERAL;
Packit Service 672cf4
Packit Service 672cf4
          inv_key = opd->result.invalid_signers;
Packit Service 672cf4
          if (inv_key)
Packit Service 672cf4
            {
Packit Service 672cf4
              for (; inv_key->next; inv_key = inv_key->next)
Packit Service 672cf4
                ;
Packit Service 672cf4
              inv_key->next = key;
Packit Service 672cf4
            }
Packit Service 672cf4
          else
Packit Service 672cf4
            opd->result.invalid_signers = key;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
      release_signatures (opd->result.signatures);
Packit Service 672cf4
      opd->result.signatures = NULL;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  if (_gpgme_debug_trace())
Packit Service 672cf4
    {
Packit Service 6c01f9
      TRACE_LOG2 ("result: invalid signers: %i, signatures: %i",
Packit Service 672cf4
		  inv_signers, signatures);
Packit Service 672cf4
      for (inv_key=opd->result.invalid_signers; inv_key; inv_key=inv_key->next)
Packit Service 672cf4
	{
Packit Service 6c01f9
	  TRACE_LOG3 ("result: invalid signer: fpr=%s, reason=%s <%s>",
Packit Service 672cf4
		      inv_key->fpr, gpgme_strerror (inv_key->reason),
Packit Service 672cf4
		      gpgme_strsource (inv_key->reason));
Packit Service 672cf4
	}
Packit Service 672cf4
      for (sig = opd->result.signatures; sig; sig = sig->next)
Packit Service 672cf4
	{
Packit Service 6c01f9
	  TRACE_LOG6 ("result: signature: type=%i, pubkey_algo=%i, "
Packit Service 672cf4
		      "hash_algo=%i, timestamp=%li, fpr=%s, sig_class=%i",
Packit Service 672cf4
		      sig->type, sig->pubkey_algo, sig->hash_algo,
Packit Service 672cf4
		      sig->timestamp, sig->fpr, sig->sig_class);
Packit Service 672cf4
	}
Packit Service 672cf4
   }
Packit Service 672cf4
Packit Service 6c01f9
  TRACE_SUC1 ("result=%p", &opd->result);
Packit Service 672cf4
  return &opd->result;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
static gpgme_error_t
Packit Service 672cf4
parse_sig_created (char *args, gpgme_new_signature_t *sigp,
Packit Service 672cf4
                   gpgme_protocol_t protocol)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_new_signature_t sig;
Packit Service 672cf4
  char *tail;
Packit Service 672cf4
Packit Service 672cf4
  sig = malloc (sizeof (*sig));
Packit Service 672cf4
  if (!sig)
Packit Service 672cf4
    return gpg_error_from_syserror ();
Packit Service 672cf4
Packit Service 672cf4
  sig->next = NULL;
Packit Service 672cf4
  switch (*args)
Packit Service 672cf4
    {
Packit Service 672cf4
    case 'S':
Packit Service 672cf4
      sig->type = GPGME_SIG_MODE_NORMAL;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case 'D':
Packit Service 672cf4
      sig->type = GPGME_SIG_MODE_DETACH;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case 'C':
Packit Service 672cf4
      sig->type = GPGME_SIG_MODE_CLEAR;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    default:
Packit Service 672cf4
      /* The backend engine is not behaving.  */
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  args++;
Packit Service 672cf4
  if (*args != ' ')
Packit Service 672cf4
    {
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  gpg_err_set_errno (0);
Packit Service 672cf4
  sig->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol);
Packit Service 672cf4
  if (errno || args == tail || *tail != ' ')
Packit Service 672cf4
    {
Packit Service 672cf4
      /* The crypto backend does not behave.  */
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
  args = tail;
Packit Service 672cf4
Packit Service 672cf4
  sig->hash_algo = strtol (args, &tail, 0);
Packit Service 672cf4
  if (errno || args == tail || *tail != ' ')
Packit Service 672cf4
    {
Packit Service 672cf4
      /* The crypto backend does not behave.  */
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
  args = tail;
Packit Service 672cf4
Packit Service 672cf4
  sig->sig_class = strtol (args, &tail, 0);
Packit Service 672cf4
  sig->class = sig->sig_class;
Packit Service 672cf4
  sig->_obsolete_class = sig->sig_class;
Packit Service 672cf4
  if (errno || args == tail || *tail != ' ')
Packit Service 672cf4
    {
Packit Service 672cf4
      /* The crypto backend does not behave.  */
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
  args = tail;
Packit Service 672cf4
Packit Service 672cf4
  sig->timestamp = _gpgme_parse_timestamp (args, &tail);
Packit Service 672cf4
  if (sig->timestamp == -1 || args == tail || *tail != ' ')
Packit Service 672cf4
    {
Packit Service 672cf4
      /* The crypto backend does not behave.  */
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
  args = tail;
Packit Service 672cf4
  while (*args == ' ')
Packit Service 672cf4
    args++;
Packit Service 672cf4
Packit Service 672cf4
  if (!*args)
Packit Service 672cf4
    {
Packit Service 672cf4
      /* The crypto backend does not behave.  */
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  tail = strchr (args, ' ');
Packit Service 672cf4
  if (tail)
Packit Service 672cf4
    *tail = '\0';
Packit Service 672cf4
Packit Service 672cf4
  sig->fpr = strdup (args);
Packit Service 672cf4
  if (!sig->fpr)
Packit Service 672cf4
    {
Packit Service 672cf4
      free (sig);
Packit Service 672cf4
      return gpg_error_from_syserror ();
Packit Service 672cf4
    }
Packit Service 672cf4
  *sigp = sig;
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
_gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  void *hook;
Packit Service 672cf4
  op_data_t opd;
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_passphrase_status_handler (priv, code, args);
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
Packit Service 672cf4
  opd = hook;
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
Packit Service 672cf4
  switch (code)
Packit Service 672cf4
    {
Packit Service 672cf4
    case GPGME_STATUS_SIG_CREATED:
Packit Service 672cf4
      opd->sig_created_seen = 1;
Packit Service 672cf4
      err = parse_sig_created (args, opd->last_sig_p, ctx->protocol);
Packit Service 672cf4
      if (err)
Packit Service 672cf4
	return err;
Packit Service 672cf4
Packit Service 672cf4
      opd->last_sig_p = &(*opd->last_sig_p)->next;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_KEY_CONSIDERED:
Packit Service 672cf4
      /* This is emitted during gpg's key lookup to give information
Packit Service 672cf4
       * about the lookup results.  We store the last one so it can be
Packit Service 672cf4
       * used in connection with INV_RECP.  */
Packit Service 672cf4
      free (opd->kc_fpr);
Packit Service 672cf4
      opd->kc_fpr = NULL;
Packit Service 672cf4
      err = _gpgme_parse_key_considered (args, &opd->kc_fpr, &opd->kc_flags);
Packit Service 672cf4
      if (err)
Packit Service 672cf4
        return err;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_INV_RECP:
Packit Service 672cf4
      if (opd->inv_sgnr_seen && opd->ignore_inv_recp)
Packit Service 672cf4
        break;
Packit Service 6c01f9
      /* FALLTROUGH */
Packit Service 672cf4
    case GPGME_STATUS_INV_SGNR:
Packit Service 672cf4
      if (code == GPGME_STATUS_INV_SGNR)
Packit Service 672cf4
        opd->inv_sgnr_seen = 1;
Packit Service 672cf4
      free (opd->kc_fpr);
Packit Service 672cf4
      opd->kc_fpr = NULL;
Packit Service 672cf4
      err = _gpgme_parse_inv_recp (args, 1, opd->kc_fpr, opd->kc_flags,
Packit Service 672cf4
                                   opd->last_signer_p);
Packit Service 672cf4
      if (err)
Packit Service 672cf4
	return err;
Packit Service 672cf4
Packit Service 672cf4
      opd->last_signer_p = &(*opd->last_signer_p)->next;
Packit Service 672cf4
      free (opd->kc_fpr);
Packit Service 672cf4
      opd->kc_fpr = NULL;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_FAILURE:
Packit Service 672cf4
      opd->failure_code = _gpgme_parse_failure (args);
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_EOF:
Packit Service 672cf4
      /* The UI server does not send information about the created
Packit Service 672cf4
         signature.  This is irrelevant for this protocol and thus we
Packit Service 672cf4
         should not check for that.  */
Packit Service 672cf4
      if (opd->result.invalid_signers)
Packit Service 672cf4
	err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
Packit Service 672cf4
      else if (!opd->sig_created_seen
Packit Service 672cf4
               && ctx->protocol != GPGME_PROTOCOL_UISERVER)
Packit Service 672cf4
	err = opd->failure_code? opd->failure_code:gpg_error (GPG_ERR_GENERAL);
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_INQUIRE_MAXLEN:
Packit Service 672cf4
      if (ctx->status_cb && !ctx->full_status)
Packit Service 672cf4
        err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    default:
Packit Service 672cf4
      break;
Packit Service 672cf4
    }
Packit Service 672cf4
  return err;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static gpgme_error_t
Packit Service 672cf4
sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_progress_status_handler (priv, code, args);
Packit Service 672cf4
  if (!err)
Packit Service 672cf4
    err = _gpgme_sign_status_handler (priv, code, args);
Packit Service 672cf4
  return err;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static gpgme_error_t
Packit Service 672cf4
sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  void *hook;
Packit Service 672cf4
  op_data_t opd;
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook,
Packit Service 672cf4
			       sizeof (*opd), release_op_data);
Packit Service 672cf4
  opd = hook;
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
  opd->failure_code = 0;
Packit Service 672cf4
  opd->last_signer_p = &opd->result.invalid_signers;
Packit Service 672cf4
  opd->last_sig_p = &opd->result.signatures;
Packit Service 672cf4
  opd->ignore_inv_recp = !!ignore_inv_recp;
Packit Service 672cf4
  opd->inv_sgnr_seen = 0;
Packit Service 672cf4
  opd->sig_created_seen = 0;
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
_gpgme_op_sign_init_result (gpgme_ctx_t ctx)
Packit Service 672cf4
{
Packit Service 672cf4
  return sign_init_result (ctx, 0);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static gpgme_error_t
Packit Service 672cf4
sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
Packit Service 672cf4
	    gpgme_data_t sig, gpgme_sig_mode_t mode)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_op_reset (ctx, synchronous);
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
Packit Service 672cf4
  /* If we are using the CMS protocol, we ignore the INV_RECP status
Packit Service 672cf4
     code if a newer GPGSM is in use.  GPGMS does not support combined
Packit Service 672cf4
     sign+encrypt and thus this can't harm.  */
Packit Service 672cf4
  err = sign_init_result (ctx, (ctx->protocol == GPGME_PROTOCOL_CMS));
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
Packit Service 672cf4
  if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
Packit Service 672cf4
      && mode != GPGME_SIG_MODE_CLEAR)
Packit Service 672cf4
    return gpg_error (GPG_ERR_INV_VALUE);
Packit Service 672cf4
Packit Service 672cf4
  if (!plain)
Packit Service 672cf4
    return gpg_error (GPG_ERR_NO_DATA);
Packit Service 672cf4
  if (!sig)
Packit Service 672cf4
    return gpg_error (GPG_ERR_INV_VALUE);
Packit Service 672cf4
Packit Service 672cf4
  if (ctx->passphrase_cb)
Packit Service 672cf4
    {
Packit Service 672cf4
      err = _gpgme_engine_set_command_handler
Packit Service 6c01f9
	(ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
Packit Service 672cf4
      if (err)
Packit Service 672cf4
	return err;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  _gpgme_engine_set_status_handler (ctx->engine, sign_status_handler,
Packit Service 672cf4
				    ctx);
Packit Service 672cf4
Packit Service 672cf4
  return _gpgme_engine_op_sign (ctx->engine, plain, sig, mode, ctx->use_armor,
Packit Service 672cf4
				ctx->use_textmode, ctx->include_certs,
Packit Service 672cf4
				ctx /* FIXME */);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
/* Sign the plaintext PLAIN and store the signature in SIG.  */
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
Packit Service 672cf4
		     gpgme_sig_mode_t mode)
Packit Service 672cf4
{
Packit Service 672cf4
  gpg_error_t err;
Packit Service 6c01f9
  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_sign_start", ctx,
Packit Service 672cf4
	      "plain=%p, sig=%p, mode=%i", plain, sig, mode);
Packit Service 672cf4
Packit Service 672cf4
  if (!ctx)
Packit Service 672cf4
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit Service 672cf4
Packit Service 672cf4
  err = sign_start (ctx, 0, plain, sig, mode);
Packit Service 672cf4
  return TRACE_ERR (err);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
/* Sign the plaintext PLAIN and store the signature in SIG.  */
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
Packit Service 672cf4
	       gpgme_sig_mode_t mode)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
Packit Service 6c01f9
  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_sign", ctx,
Packit Service 672cf4
	      "plain=%p, sig=%p, mode=%i", plain, sig, mode);
Packit Service 672cf4
Packit Service 672cf4
  if (!ctx)
Packit Service 672cf4
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
Packit Service 672cf4
Packit Service 672cf4
  err = sign_start (ctx, 1, plain, sig, mode);
Packit Service 672cf4
  if (!err)
Packit Service 672cf4
    err = _gpgme_wait_one (ctx);
Packit Service 672cf4
  return TRACE_ERR (err);
Packit Service 672cf4
}