/* Created a detached signature for INDATA and write it to OUTDATA. On termination of the signing command engine_private_finished() is called with FILTER as the first argument. */ int op_gpgme_sign (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t filter, void *hwnd) { gpg_error_t err; closure_data_t cld; gpgme_ctx_t ctx = NULL; gpgme_key_t sign_key = NULL; (void)hwnd; if (signer_dialog_box (&sign_key, NULL, 0) == -1) { log_debug ("%s:%s: leave (dialog failed)\n", SRCNAME, __func__); return gpg_error (GPG_ERR_CANCELED); } cld = xcalloc (1, sizeof *cld); cld->closure = sign_closure; cld->filter = filter; err = gpgme_new (&ctx); if (err) goto leave; gpgme_set_progress_cb (ctx, NULL, cld); switch (protocol) { case PROTOCOL_OPENPGP: /* Gpgme's default. */ break; case PROTOCOL_SMIME: err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); break; default: err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); break; } if (err) goto leave; gpgme_set_armor (ctx, 1); gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cld->pw_cb); cld->pw_cb.ctx = ctx; cld->pw_cb.ttl = opt.passwd_ttl; err = gpgme_signers_add (ctx, sign_key); if (!err) err = gpgme_op_sign_start (ctx, indata, outdata, GPGME_SIG_MODE_DETACH); leave: if (err) { xfree (cld); gpgme_release (ctx); } else engine_private_set_cancel (filter, ctx); gpgme_key_unref (sign_key); return err; }
/** * seahorse_service_crypto_sign_text: * @crypto: SeahorseServiceCrypto * @signer: the signer keyid * @flags: 0 (ignored) * @cleartext: the text to sign * @crypttext: the clear text signature (out) (GPGME_SIG_MODE_CLEAR) * @error: an error to return * * DBus: SignText * * Signs the @cleartext and returns the signature in @crypttext * * Returns: TRUE on success */ gboolean seahorse_service_crypto_sign_text (SeahorseServiceCrypto *crypto, const char *signer, int flags, const char *cleartext, char **crypttext, GError **error) { SeahorseObject *signkey = NULL; gpgme_error_t gerr; SeahorseGpgmeOperation *pop; gpgme_data_t plain, cipher; gboolean ret = TRUE; /* * TODO: Once we support different kinds of keys that support encryption * then all this logic will need to change. */ /* The signer */ if (!signer || !signer[0]) g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("No signer specified")); signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer); if (!signkey) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Invalid or unrecognized signer: %s"), signer); return FALSE; } if (!SEAHORSE_IS_GPGME_KEY (signkey) || !(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Key is not valid for signing: %s"), signer); return FALSE; } pop = seahorse_gpgme_operation_new (NULL); /* new data from text */ gerr = gpgme_data_new_from_mem (&plain, cleartext, strlen (cleartext), FALSE); g_return_val_if_fail (GPG_IS_OK (gerr), FALSE); gerr = gpgme_data_new (&cipher); g_return_val_if_fail (GPG_IS_OK (gerr), FALSE); /* encrypt with armor */ gpgme_set_textmode (pop->gctx, TRUE); gpgme_set_armor (pop->gctx, TRUE); /* Do the signage */ gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey))); gerr = gpgme_op_sign_start (pop->gctx, plain, cipher, GPGME_SIG_MODE_CLEAR); /* Frees cipher */ ret = process_crypto_result (pop, gerr, cipher, crypttext, NULL, error); g_object_unref (pop); gpgme_data_release (plain); return ret; }
static gboolean sign_start (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata, SeahorsePGPOperation *pop, GError **err) { gpgme_data_t cipher; gpgme_error_t gerr; gchar *touri; g_assert (mode->signer); /* File to encrypt to */ touri = seahorse_util_add_suffix (uri, SEAHORSE_SIG_SUFFIX, _("Choose Signature File Name for '%s'")); if (!touri) return FALSE; /* Open necessary files, release these with the operation */ cipher = seahorse_vfs_data_create (touri, SEAHORSE_VFS_WRITE | SEAHORSE_VFS_DELAY, err); g_free (touri); if (!cipher) return FALSE; g_object_set_data_full (G_OBJECT (pop), "cipher-data", cipher, (GDestroyNotify)gpgme_data_release); gpgme_set_armor (pop->gctx, seahorse_gconf_get_boolean (ARMOR_KEY)); gpgme_set_textmode (pop->gctx, FALSE); /* Start actual signage */ gpgme_signers_clear (pop->gctx); gpgme_signers_add (pop->gctx, mode->signer); gerr = gpgme_op_sign_start (pop->gctx, uridata, cipher, GPGME_SIG_MODE_DETACH); if (gerr != 0) { seahorse_util_gpgme_to_error (gerr, err); return FALSE; } return TRUE; }
static gpg_error_t gpa_file_sign_operation_start (GpaFileSignOperation *op, gpa_file_item_t file_item) { gpg_error_t err; if (file_item->direct_in) { /* No copy is made. */ err = gpgme_data_new_from_mem (&op->plain, file_item->direct_in, file_item->direct_in_len, 0); if (err) { gpa_gpgme_warning (err); return err; } err = gpgme_data_new (&op->sig); if (err) { gpa_gpgme_warning (err); gpgme_data_release (op->plain); op->plain = NULL; return err; } } else { gchar *plain_filename = file_item->filename_in; char *filename_used; file_item->filename_out = destination_filename (plain_filename, gpgme_get_armor (GPA_OPERATION (op)->context->ctx), gpgme_get_protocol (GPA_OPERATION (op)->context->ctx), op->sign_type); /* Open the files */ op->plain_fd = gpa_open_input (plain_filename, &op->plain, GPA_OPERATION (op)->window); if (op->plain_fd == -1) /* FIXME: Error value. */ return gpg_error (GPG_ERR_GENERAL); op->sig_fd = gpa_open_output (file_item->filename_out, &op->sig, GPA_OPERATION (op)->window, &filename_used); if (op->sig_fd == -1) { gpgme_data_release (op->plain); close (op->plain_fd); xfree (filename_used); /* FIXME: Error value. */ return gpg_error (GPG_ERR_GENERAL); } xfree (file_item->filename_out); file_item->filename_out = filename_used; } /* Start the operation */ err = gpgme_op_sign_start (GPA_OPERATION (op)->context->ctx, op->plain, op->sig, op->sign_type); if (err) { gpa_gpgme_warning (err); return err; } /* Show and update the progress dialog */ gtk_widget_show_all (GPA_FILE_OPERATION (op)->progress_dialog); gpa_progress_dialog_set_label (GPA_PROGRESS_DIALOG (GPA_FILE_OPERATION (op)->progress_dialog), file_item->direct_name ? file_item->direct_name : file_item->filename_in); return 0; }