int geanypg_sign_selection_dialog(encrypt_data * ed) { GtkWidget * dialog = gtk_dialog_new(); unsigned long idx; int response; GtkWidget * contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); GtkWidget * combobox = geanypg_combobox( geanypg_makelist(ed->skey_array, ed->nskeys, 0)); gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Choose a key to sign with:")), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(contentarea), combobox, TRUE, TRUE, 0); // add ok and cancel buttons gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_widget_show_all(dialog); gtk_window_set_title(GTK_WINDOW(dialog), _("Select signer")); // make sure dialog is destroyed when user responds response = gtk_dialog_run(GTK_DIALOG(dialog)); if (response == GTK_RESPONSE_CANCEL) { gtk_widget_destroy(dialog); return 0; } idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox)); gpgme_signers_clear(ed->ctx); if (idx < ed->nskeys) gpgme_signers_add(ed->ctx, ed->skey_array[idx]); gtk_widget_destroy(dialog); return 1; }
void GPGWrapper::init() { if (initialized) return; initialized = true; gpgme_check_version(NULL); setlocale(LC_ALL, ""); gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL)); #ifdef LC_MESSAGES gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL)); #endif gpgme_error_t error = gpgme_new(&context); fail_if_err(error, L"Nie uda³o siê zainicjowaæ kontekstu GPG."); gpgme_set_textmode(context, 1); gpgme_set_armor(context, 1); error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); fail_if_err(error, L"Nie zainstalowano OpenPGP."); error = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP); fail_if_err(error, L"Nie uda³o siê ustawiæ OpenPGP."); privateKey = getPrivateKey(privateKeyId.c_str()); error = gpgme_signers_add(context, privateKey); fail_if_err(error, L"Nie uda³o siê ustawiæ klucza prywatnego."); }
static int pygpgme_context_set_signers(PyGpgmeContext *self, PyObject *value) { PyObject *signers = NULL; int i, length, ret = 0; if (value == NULL) { PyErr_SetString(PyExc_AttributeError, "Can not delete attribute"); return -1; } signers = PySequence_Fast(value, "signers must be a sequence of keys"); if (!signers) { ret = -1; goto end; } gpgme_signers_clear(self->ctx); length = PySequence_Fast_GET_SIZE(signers); for (i = 0; i < length; i++) { PyObject *item = PySequence_Fast_GET_ITEM(signers, i); if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) { PyErr_SetString(PyExc_TypeError, "signers must be a sequence of keys"); ret = -1; goto end; } gpgme_signers_add(self->ctx, ((PyGpgmeKey *)item)->key); } end: Py_XDECREF(signers); return ret; }
/* 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 pkcs7_add_signer (Pkcs7Ctx *pkcs7, const char *signer, GError **err) { gpgme_key_t key = NULL; if (!(key = pkcs7_get_key_by_name (pkcs7, signer, TRUE, err))) return FALSE; /* set the key (the previous operation guaranteed that it exists, no need * 2 check return values...) */ gpgme_signers_add (pkcs7->ctx, key); gpgme_key_unref (key); return TRUE; }
void crypto_asym::set_signatories(const std::vector<std::string> & signatories) { #if GPGME_SUPPORT gpgme_key_t *signatories_key = NULL; if(signatories.empty()) { gpgme_signers_clear(context); has_signatories = false; } else { build_key_list(signatories, signatories_key, true); try { gpgme_signers_clear(context); gpgme_key_t *ptr = signatories_key; gpgme_error_t err; if(ptr == NULL) throw SRC_BUG; // build_key_list failed while(*ptr != NULL) { err = gpgme_signers_add(context, *ptr); switch(gpgme_err_code(err)) { case GPG_ERR_NO_ERROR: break; default: throw Erange("crypto_asym::encrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } ++ptr; } } catch(...) { release_key_list(signatories_key); gpgme_signers_clear(context); has_signatories = false; throw; } release_key_list(signatories_key); has_signatories = true; } #else throw Efeature("Asymetric Strong encryption algorithms using GPGME"); #endif }
/* * Setting the signers and the protocol for the context. The protocol * to use is derived from the keys. An errro will be displayed if the * selected keys are not all of one protocol. */ static gboolean set_signers (GpaFileSignOperation *op, GList *signers) { GList *cur; gpg_error_t err; gpgme_protocol_t protocol = GPGME_PROTOCOL_UNKNOWN; gpgme_signers_clear (GPA_OPERATION (op)->context->ctx); if (!signers) { /* Can't happen */ gpa_window_error (_("You didn't select any key for signing"), GPA_OPERATION (op)->window); return FALSE; } for (cur = signers; cur; cur = g_list_next (cur)) { gpgme_key_t key = cur->data; if (protocol == GPGME_PROTOCOL_UNKNOWN) protocol = key->protocol; else if (key->protocol != protocol) { /* Should not happen because the selection dialog should have not allowed to select different key types. */ gpa_window_error (_("The selected certificates are not all of the same type." " That is, you mixed OpenPGP and X.509 certificates." " Please make sure to select only certificates of the" " same type."), GPA_OPERATION (op)->window); return FALSE; } } gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, protocol); for (cur = signers; cur; cur = g_list_next (cur)) { gpgme_key_t key = cur->data; err = gpgme_signers_add (GPA_OPERATION (op)->context->ctx, key); if (err) gpa_gpgme_error (err); } return TRUE; }
static gboolean encrypt_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->recipients && mode->recipients[0]); /* File to encrypt to */ touri = seahorse_util_add_suffix (uri, SEAHORSE_CRYPT_SUFFIX, _("Choose Encrypted 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 encryption */ gpgme_signers_clear (pop->gctx); if (mode->signer) { gpgme_signers_add (pop->gctx, mode->signer); gerr = gpgme_op_encrypt_sign_start (pop->gctx, mode->recipients, GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher); } else { gerr = gpgme_op_encrypt_start (pop->gctx, mode->recipients, GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher); } if (gerr != 0) { seahorse_util_gpgme_to_error (gerr, err); return FALSE; } return TRUE; }
/* * Add signer to ctx's list of signers and return TRUE on success or FALSE * on error. */ static gboolean gpgme_add_signer(gpgme_ctx_t ctx, const gchar * signer, GtkWindow * parent, GError ** error) { gpgme_key_t key = NULL; /* note: private (secret) key has never low trust... */ if (! (key = get_key_from_name(ctx, signer, TRUE, FALSE, parent, error))) return FALSE; /* set the key (the previous operation guaranteed that it exists, no * need 2 check return values...) */ gpgme_signers_add(ctx, key); gpgme_key_unref(key); return TRUE; }
/* Sign this key with the given private key. */ gpg_error_t gpa_gpgme_edit_sign_start (GpaContext *ctx, gpgme_key_t key, gpgme_key_t secret_key, gboolean local) { struct edit_parms_s *parms = NULL; gpg_error_t err = gpg_error (GPG_ERR_NO_ERROR); gpgme_data_t out; err = gpgme_data_new (&out); if (gpg_err_code (err) != GPG_ERR_NO_ERROR) { return err; } gpgme_signers_clear (ctx->ctx); err = gpgme_signers_add (ctx->ctx, secret_key); if (gpg_err_code (err) != GPG_ERR_NO_ERROR) { return err; } parms = gpa_gpgme_edit_sign_parms_new (ctx, "0", local, out); err = gpgme_op_edit_start (ctx->ctx, key, edit_fnc, parms, out); return err; }
/* The main GPG encryption routine for libfko. */ int gpgme_encrypt(fko_ctx_t fko_ctx, unsigned char *indata, size_t in_len, const char *pw, unsigned char **out, size_t *out_len) { char *tmp_buf; int res; gpgme_ctx_t gpg_ctx = NULL; gpgme_data_t cipher = NULL; gpgme_data_t plaintext = NULL; gpgme_key_t key[2] = { NULL, NULL }; gpgme_error_t err; /* Initialize gpgme */ res = init_gpgme(fko_ctx); if(res != FKO_SUCCESS) return(res); gpg_ctx = fko_ctx->gpg_ctx; /* Initialize the plaintext data (place into gpgme_data object) */ err = gpgme_data_new_from_mem(&plaintext, (char*)indata, in_len, 1); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ); } /* Set protocol */ err = gpgme_set_protocol(gpg_ctx, GPGME_PROTOCOL_OpenPGP); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_SET_PROTOCOL); } /* Set ascii-armor off (we will be base64-encoding the encrypted data * ourselves. */ gpgme_set_armor(gpg_ctx, 0); /* The gpgme_encrypt.... functions take a recipient key array, so we add * our single key here. */ key[0] = fko_ctx->recipient_key; /* Create the buffer for our encrypted data. */ err = gpgme_data_new(&cipher); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_CIPHER_DATA_OBJ); } /* Here we add the signer to the gpgme context if there is one. */ if(fko_ctx->gpg_signer != NULL) { gpgme_signers_clear(gpg_ctx); err = gpgme_signers_add(gpg_ctx, fko_ctx->signer_key); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_ADD_SIGNER); } } /* Set the passphrase callback. */ gpgme_set_passphrase_cb(gpg_ctx, my_passphrase_cb, (void*)pw); /* Encrypt and sign (if a sig was provided) the SPA data. */ if(fko_ctx->gpg_signer == NULL) err = gpgme_op_encrypt( gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher ); else err = gpgme_op_encrypt_sign( gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher ); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; if(gpgme_err_code(err) == GPG_ERR_CANCELED) return(FKO_ERROR_GPGME_BAD_PASSPHRASE); return(FKO_ERROR_GPGME_ENCRYPT_SIGN); } /* Done with the plaintext. */ gpgme_data_release(plaintext); /* Get the encrypted data and its length from the gpgme data object. * BTW, this does free the memory used by cipher. */ tmp_buf = gpgme_data_release_and_get_mem(cipher, out_len); *out = malloc(*out_len); /* This is freed upon fko_ctx destruction. */ if(*out == NULL) res = FKO_ERROR_MEMORY_ALLOCATION; else { memcpy(*out, tmp_buf, *out_len); res = FKO_SUCCESS; } gpgme_free(tmp_buf); return(res); }
QString QalfCrypto::sign(QString &message, QString &key) { gpgme_key_t gpgkey ; gpgme_data_t signature ; gpgme_data_t msg ; gpgme_verify_result_t verification ; gpgme_signature_t signatures ; gpgme_error_t result ; char * buffer ; gpgme_set_passphrase_cb(context,&passphrase_callback,NULL) ; result = gpgme_set_protocol(context,GPGME_PROTOCOL_OpenPGP) ; Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR) ; gpgme_set_armor(context,1) ; gpgme_set_textmode(context,1) ; gpgme_signers_clear(context) ; result = gpgme_set_keylist_mode(context,GPGME_KEYLIST_MODE_LOCAL) ; // retrieving key result = gpgme_get_key(context, key.toAscii().data(),&gpgkey,1) ; Q_ASSERT(result == GPG_ERR_NO_ERROR) ; Q_ASSERT(gpgkey != 0) ; // signing result = gpgme_signers_add(context,gpgkey) ; Q_ASSERT(result == GPG_ERR_NO_ERROR) ; result = gpgme_data_new(&signature); Q_ASSERT(result == GPG_ERR_NO_ERROR) ; int message_length = message.toAscii().size() ; char * message_char = (char *) calloc(message_length+1,sizeof(char)) ; memcpy(message_char,message.toAscii().data(),message_length) ; // printf("memcmp : %d\n",memcmp(message_char,"1fc36e1d41a93c1d79f6872198f426129320d287",message_length+1)) ; result = gpgme_data_new_from_mem(&msg,message_char,message_length,0) ; gpgme_data_seek(signature,0,SEEK_SET) ; gpgme_data_seek(msg,0,SEEK_SET) ; result = gpgme_op_sign(context, msg,signature, GPGME_SIG_MODE_DETACH) ; Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR || gpgme_err_code(result) == GPG_ERR_BAD_PASSPHRASE || gpgme_err_code(result) == GPG_ERR_CANCELED) ; // gpgme_data_seek(signature,0,SEEK_SET) ; // gpgme_data_seek(msg,0,SEEK_SET) ; // // result = gpgme_op_verify (context, signature, msg , 0) ; // Q_ASSERT(gpgme_err_code(result) != GPG_ERR_INV_VALUE) ; // Q_ASSERT(gpgme_err_code(result) != GPG_ERR_NO_DATA) ; // Q_ASSERT(result == GPG_ERR_NO_ERROR) ; // // verification = gpgme_op_verify_result(context) ; // Q_ASSERT(verification != 0) ; // // signatures = verification->signatures ; // Q_ASSERT(verification->signatures != 0) ; // result = signatures->status ; // printf("status : %d\n",gpgme_err_code(result)) ; // printf("signature summary : %d\n",signatures->summary) ; // Q_ASSERT(signatures->summary == GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN) ; // QString signatureStr ; buffer = (char *) calloc(2048,sizeof(char)) ; gpgme_data_seek(signature,0,SEEK_SET) ; gpgme_data_read(signature,buffer,2048) ; signatureStr += buffer ; qDebug() << "signature" << signatureStr ; gpgme_data_release(signature) ; gpgme_key_unref(gpgkey) ; gpgme_data_release(msg) ; return signatureStr ; }
/** * crypto: the crypto service (#SeahorseServiceCrypto) * recipients: A list of recipients (keyids "openpgp:B8098FB063E2C811") * Must be empty when symmetric encryption is used. * signer: optional, the keyid of the signer * flags: FLAG_SYMMETRIC to perform symmetric encryption * cleartext: the text to encrypt * clearlength: Length of the cleartext * crypttext: the encrypted text (out) * cryptlength: the length of this text (out) * textmode: TRUE if gpgme should use textmode * ascii_armor: TRUE if GPGME should use ascii armor * error: The Error * * Handles encryption in a generic way. Can be used by several DBus APIs * * Returns TRUE on success **/ static gboolean crypto_encrypt_generic (SeahorseServiceCrypto *crypto, const char **recipients, const char *signer, int flags, const char *cleartext, gsize clearlength, char **crypttext, gsize *cryptlength, gboolean textmode, gboolean ascii_armor, GError **error) { GList *recipkeys = NULL; SeahorseGpgmeOperation *pop; SeahorseObject *signkey = NULL; SeahorseObject *skey; gpgme_key_t *recips; gboolean symmetric = FALSE; gpgme_data_t plain, cipher; gpgme_error_t gerr; gboolean ret = TRUE; GSettings *settings; gchar *keyid; if ((flags & FLAG_SYMMETRIC) == FLAG_SYMMETRIC) symmetric = TRUE; if (symmetric && recipients[0] != NULL) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Recipients specified for symmetric encryption")); return FALSE; } /* The signer */ if (signer && signer[0]) { 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; } } if (!symmetric) { /* The recipients */ for( ; recipients[0]; recipients++) { skey = seahorse_context_object_from_dbus (SCTX_APP (), recipients[0]); if (!skey) { g_list_free (recipkeys); g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Invalid or unrecognized recipient: %s"), recipients[0]); return FALSE; } if (!SEAHORSE_IS_GPGME_KEY (skey) || !(seahorse_object_get_flags (skey) & SEAHORSE_FLAG_CAN_ENCRYPT)) { g_list_free (recipkeys); g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Key is not a valid recipient for encryption: %s"), recipients[0]); return FALSE; } recipkeys = g_list_prepend (recipkeys, SEAHORSE_PGP_KEY (skey)); } if (!recipkeys) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("No recipients specified")); return FALSE; } } pop = seahorse_gpgme_operation_new (NULL); /* new data form text */ gerr = gpgme_data_new_from_mem (&plain, cleartext, clearlength, 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, textmode); gpgme_set_armor (pop->gctx, ascii_armor); if (symmetric) { /* gpgme_op_encrypt{_sign,}_start() will perform symmetric encryption * when no recipients are specified. */ recips = NULL; } else { /* Add the default key if set and necessary */ settings = g_settings_new ("org.gnome.crypto.pgp"); if (g_settings_get_boolean (settings, "encrypt-to-self")) { keyid = g_settings_get_string (settings, "default-key"); if (keyid && keyid[0]) { skey = seahorse_context_find_object (NULL, g_quark_from_string (keyid), SEAHORSE_LOCATION_LOCAL); if (SEAHORSE_IS_PGP_KEY (skey)) recipkeys = g_list_append (recipkeys, skey); } g_free (keyid); } g_object_unref (settings); /* Make keys into the right format for GPGME */ recips = keylist_to_keys (recipkeys); g_list_free (recipkeys); } /* Do the encryption */ if (signkey) { gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey))); gerr = gpgme_op_encrypt_sign_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher); } else { gerr = gpgme_op_encrypt_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher); } free_keys (recips); /* Frees cipher */ ret = process_crypto_result (pop, gerr, cipher, crypttext, cryptlength, error); g_object_unref (pop); gpgme_data_release (plain); return ret; }
/** * crypto: the crypto service (#SeahorseServiceCrypto) * recipients: A list of recipients (keyids "openpgp:B8098FB063E2C811") * signer: optional, the keyid of the signer * flags: 0, not used * cleartext: the text to encrypt * clearlength: Length of the cleartext * crypttext: the encrypted text (out) * cryptlength: the length of this text (out) * textmode: TRUE if gpgme should use textmode * ascii_armor: TRUE if GPGME should use ascii armor * error: The Error * * Handles encryption in a generic way. Can be used by several DBus APIs * * Returns TRUE on success **/ static gboolean crypto_encrypt_generic (SeahorseServiceCrypto *crypto, const char **recipients, const char *signer, int flags, const char *cleartext, gsize clearlength, char **crypttext, gsize *cryptlength, gboolean textmode, gboolean ascii_armor, GError **error) { GList *recipkeys = NULL; SeahorseGpgmeOperation *pop; SeahorseObject *signkey = NULL; SeahorseObject *skey; gpgme_key_t *recips; gpgme_data_t plain, cipher; gpgme_error_t gerr; 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]) { 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; } } /* The recipients */ for( ; recipients[0]; recipients++) { skey = seahorse_context_object_from_dbus (SCTX_APP (), recipients[0]); if (!skey) { g_list_free (recipkeys); g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Invalid or unrecognized recipient: %s"), recipients[0]); return FALSE; } if (!SEAHORSE_IS_GPGME_KEY (skey) || !(seahorse_object_get_flags (skey) & SEAHORSE_FLAG_CAN_ENCRYPT)) { g_list_free (recipkeys); g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Key is not a valid recipient for encryption: %s"), recipients[0]); return FALSE; } recipkeys = g_list_prepend (recipkeys, SEAHORSE_PGP_KEY (skey)); } if (!recipkeys) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("No recipients specified")); return FALSE; } pop = seahorse_gpgme_operation_new (NULL); /* new data form text */ gerr = gpgme_data_new_from_mem (&plain, cleartext, clearlength, 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, textmode); gpgme_set_armor (pop->gctx, ascii_armor); /* Add the default key if set and necessary */ if (seahorse_gconf_get_boolean (ENCRYPTSELF_KEY)) { skey = SEAHORSE_OBJECT (seahorse_context_get_default_key (SCTX_APP ())); if (SEAHORSE_IS_PGP_KEY (skey)) recipkeys = g_list_append (recipkeys, skey); } /* Make keys into the right format for GPGME */ recips = keylist_to_keys (recipkeys); g_list_free (recipkeys); /* Do the encryption */ if (signkey) { gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey))); gerr = gpgme_op_encrypt_sign_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher); } else { gerr = gpgme_op_encrypt_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher); } free_keys (recips); /* Frees cipher */ ret = process_crypto_result (pop, gerr, cipher, crypttext, cryptlength, error); g_object_unref (pop); gpgme_data_release (plain); return ret; }
int geanypg_encrypt_selection_dialog(encrypt_data * ed, gpgme_key_t ** selected, int * sign) { GtkWidget * dialog = gtk_dialog_new(); unsigned long idx, sidx, capacity; int response; GtkWidget * contentarea, * listview, * scrollwin, * combobox; GtkTreeIter iter; listdata data; gboolean active; *sign = 0; GtkListStore * list = geanypg_makelist(ed->key_array, ed->nkeys, 0); listview = geanypg_listview(list, &data); scrollwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), listview); gtk_widget_set_size_request(scrollwin, 500, 160); combobox = geanypg_combobox(geanypg_makelist(ed->skey_array, ed->nskeys, 1)); contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Please select any recipients")), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(contentarea), scrollwin, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Sign the message as:")), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(contentarea), combobox, FALSE, FALSE, 0); // add ok and cancel buttons gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_window_set_title(GTK_WINDOW(dialog), _("Select recipients")); gtk_widget_show_all(dialog); // make sure dialog is destroyed when user responds response = gtk_dialog_run(GTK_DIALOG(dialog)); if (response == GTK_RESPONSE_CANCEL) { gtk_widget_destroy(dialog); return 0; } idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox)); if (idx && idx <= ed->nskeys) { *sign = 1; gpgme_signers_add(ed->ctx, ed->skey_array[idx - 1]); // -1 because the first option is `None' } // try to loop all the keys in the list // if they are active (the user checked the checkbox in front of the key) // add it to the selected array, finaly make sure that the array // is NULL terminated if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter)) { capacity = SIZE; *selected = (gpgme_key_t*) malloc(SIZE * sizeof(gpgme_key_t)); idx = 0; sidx = 0; gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, TOGGLE_COLUMN, &active, -1); if (active) (*selected)[sidx++] = ed->key_array[idx]; while (gtk_tree_model_iter_next(GTK_TREE_MODEL(list), &iter)) { ++idx; gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, TOGGLE_COLUMN, &active, -1); if (active) (*selected)[sidx++] = ed->key_array[idx]; if (sidx >= capacity - 1) { capacity += SIZE; *selected = (gpgme_key_t*) realloc(*selected, capacity * sizeof(gpgme_key_t)); } } (*selected)[sidx] = NULL; } else { gtk_widget_destroy(dialog); return 0; } gtk_widget_destroy(dialog); return 1; }
/* ------------------ * sign a plain string with the key found with fingerprint fpr * FREE MEMORY AFTER USAGE OF RETURN VALUE! * ------------------ */ static char* sign(const char* plain_str,const char* fpr) { gpgme_error_t error; gpgme_ctx_t ctx; gpgme_key_t key; gpgme_data_t plain,sig; const int MAX_LEN = 10000; char *sig_str = NULL; char *sig_str_dup = NULL; size_t len = 0; // connect to gpgme gpgme_check_version (NULL); error = gpgme_new(&ctx); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_new failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); return NULL; } // get key by fingerprint error = gpgme_get_key(ctx,fpr,&key,1); if (error || !key) { purple_debug_error(PLUGIN_ID,"gpgme_get_key failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return NULL; } // select signers gpgme_signers_clear(ctx); error = gpgme_signers_add (ctx,key); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_signers_add failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return NULL; } // create data containers gpgme_data_new_from_mem (&plain, plain_str,strlen(plain_str),1); gpgme_data_new(&sig); // sign message, ascii armored gpgme_set_armor(ctx,1); error = gpgme_op_sign(ctx,plain,sig,GPGME_SIG_MODE_DETACH); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_op_sign failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return NULL; } // release memory for data containers gpgme_data_release(plain); sig_str = gpgme_data_release_and_get_mem(sig,&len); if (sig_str != NULL) { sig_str[len] = 0; sig_str_dup = str_unarmor(sig_str); } gpgme_free(sig_str); // close gpgme connection gpgme_release (ctx); return sig_str_dup; }
gpointer sign_file (const gchar *input_file_path, const gchar *fpr) { gpgme_error_t error; gpgme_ctx_t context; gpgme_key_t signing_key; gpgme_data_t clear_text, signed_text; gpgme_sign_result_t result; gchar *buffer; gssize nbytes; error = gpgme_new (&context); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); return GPGME_ERROR; } gpgme_set_armor (context, 0); error = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (context); return GPGME_ERROR; } const char *keyring_dir = gpgme_get_dirinfo ("homedir"); error = gpgme_ctx_set_engine_info (context, GPGME_PROTOCOL_OpenPGP, NULL, keyring_dir); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (context); return GPGME_ERROR; } error = gpgme_get_key (context, fpr, &signing_key, 1); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (context); return GPGME_ERROR; } error = gpgme_signers_add (context, signing_key); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (NULL, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } FILE *infp = g_fopen (input_file_path, "r"); if (infp == NULL) { g_printerr ("Couldn't open input file\n"); cleanup (NULL, NULL, NULL, NULL, &signing_key, &context); return FILE_OPEN_ERROR; } error = gpgme_data_new_from_stream (&clear_text, infp); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } error = gpgme_data_new (&signed_text); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } error = gpgme_op_sign (context, clear_text, signed_text, GPGME_SIG_MODE_DETACH); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } result = gpgme_op_sign_result (context); if (result->invalid_signers) { g_printerr ("Invalid signer found: %s\n", result->invalid_signers->fpr); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } if (!result->signatures || result->signatures->next) { g_printerr ("Unexpected number of signatures created\n"); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } error = gpgme_data_seek (signed_text, 0, SEEK_SET); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } buffer = g_try_malloc0 (SIG_MAXLEN); if (buffer == NULL) { g_printerr ("Couldn't allocate memory\n"); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return MEMORY_ALLOCATION_ERROR; } nbytes = gpgme_data_read (signed_text, buffer, SIG_MAXLEN); if (nbytes == -1) { g_printerr ("Error while reading data\n"); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } GError *gerr = NULL; gchar *output_file_path = g_strconcat (input_file_path, ".sig", NULL); GFile *fpout = g_file_new_for_path (output_file_path); GFileOutputStream *ostream = g_file_append_to (fpout, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &gerr); if (gerr != NULL) { g_printerr ("Couldn't open output file for writing\n"); cleanup (infp, fpout, NULL, output_file_path, &signing_key, &context); return FILE_OPEN_ERROR; } gssize wbytes = g_output_stream_write (G_OUTPUT_STREAM (ostream), buffer, nbytes, NULL, &gerr); if (wbytes == -1) { g_printerr ("Couldn't write the request number of bytes (%s)\n", gerr->message); cleanup (infp, fpout, ostream, output_file_path, &signing_key, &context); return FILE_WRITE_ERROR; } cleanup (infp, fpout, ostream, output_file_path, &signing_key, &context); return SIGN_OK; }
int main (int argc, char **argv) { int last_argc = -1; gpgme_error_t err; gpgme_ctx_t ctx; const char *key_string = NULL; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_CLEAR; gpgme_data_t in, out; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) show_usage (0); else if (!strcmp (*argv, "--key")) { argc--; argv++; if (!argc) show_usage (1); key_string = *argv; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) show_usage (1); } if (argc != 1) show_usage (1); init_gpgme (protocol); err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_protocol (ctx, protocol); gpgme_set_armor (ctx, 1); if (key_string) { gpgme_key_t akey; err = gpgme_get_key (ctx, key_string, &akey, 1); if (err) { exit (1); } err = gpgme_signers_add (ctx, akey); fail_if_err (err); gpgme_key_unref (akey); } err = gpgme_data_new_from_file (&in, *argv, 1); if (err) { fprintf (stderr, PGM ": error reading `%s': %s\n", *argv, gpg_strerror (err)); exit (1); } err = gpgme_data_new (&out); fail_if_err (err); err = gpgme_op_sign (ctx, in, out, sigmode); if (err) { fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err)); exit (1); } print_data (out); gpgme_data_release (out); gpgme_data_release (in); gpgme_release (ctx); return 0; }
/* ############################################################################# * * Description encrypt the given buffer and return the encrypted data with * an updated size information * Author Harry Brueckner * Date 2005-03-31 * Arguments char* buffer - buffer to encrypt * int size - size of the buffer * char** newbuffer - pointer to the new buffer which holds the * encrypted data * int* newsize - size of the returned buffer * PASSPHRASE_FN password_cb - callback function pointer used * to get the current passphrase * SHOWERROR_FN showerror_cb - callback function pointer used * to display errors * Return 0 if ok, otherwise 1 */ int gpgEncrypt(char* buffer, int size, char** newbuffer, int* newsize, PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb) { gpgme_ctx_t context; gpgme_data_t input, output; gpgme_encrypt_result_t result; gpgme_error_t error; gpgme_key_t* key = NULL; gpgme_key_t tkey = NULL; gpgme_sign_result_t sign_result; int i, keys = 0, showerror = 1; char* agent; char* fpr; char* tmpbuffer = NULL; TRACE(99, "gpgEncrypt()", NULL); /* we set our passphrase callback function */ passphrase_callback = password_cb; /* we initialize the external size data */ newsize[0] = 0; error = gpgme_new(&context); if (!error) { gpgme_set_textmode(context, 1); gpgme_set_armor(context, 1); /* Flawfinder: ignore */ agent = getenv("GPG_AGENT_INFO"); if (!(agent && strchr(agent, ':'))) { retries = 0; gpgme_set_passphrase_cb(context, gpgRequestPassphrase, NULL); } } if (!error) { error = gpgme_data_new_from_mem(&input, buffer, size, 0); } if (!error) { error = gpgme_data_new(&output); } if (!error) { gpgme_signers_clear(context); } if (!error) { /* allocate the keys */ keys = keyCount(); key = memAlloc(__FILE__, __LINE__, sizeof(gpgme_key_t) * (keys + 1)); key[keys] = NULL; signers = 0; for (i = 0; i < keys && !error; i++) { /* add all keys */ fpr = gpgGetFingerprint(keyGet(i), LIST_SECRET); if (fpr) { error = gpgme_get_key(context, fpr, &tkey, LIST_SECRET); if (tkey -> secret); { error = gpgme_signers_add(context, tkey); signers++; } memFreeString(__FILE__, __LINE__, fpr); } fpr = gpgGetFingerprint(keyGet(i), LIST_ALL); if (fpr) { error = gpgme_get_key(context, fpr, &key[i], LIST_ALL); memFreeString(__FILE__, __LINE__, fpr); } } } if (signers > 1) { /* as soon as we get two signers, we must no longer cache anything */ config -> keeppassphrase = 0; clearPassphrase(1); } /* encrypt and sign the data */ if (!error) { error = gpgme_op_encrypt_sign(context, key, GPGME_ENCRYPT_ALWAYS_TRUST, input, output); } /* we don't need the passphrase any longer */ clearPassphrase(0); if (!error) { result = gpgme_op_encrypt_result(context); } if (!error && result -> invalid_recipients) { tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH); snprintf(tmpbuffer, STDBUFFERLENGTH, _("Invalid recipient encountered: %s"), result -> invalid_recipients -> fpr); (showerror_cb)(_("GpgMe error"), tmpbuffer); memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH); showerror = 0; error = 1; } if (!error) { sign_result = gpgme_op_sign_result(context); error = gpgCheckSignResult(showerror_cb, sign_result, GPGME_SIG_MODE_NORMAL); showerror = !error; } if (!error) { tmpbuffer = gpgData2Char(output, newsize); } /* free the keys again */ i = 0; while (key && keys && key[i]) { gpgme_key_unref(key[i++]); } memFree(__FILE__, __LINE__, key, sizeof(gpgme_key_t) * (keys + 1)); gpgme_data_release(input); gpgme_data_release(output); gpgme_release(context); *newbuffer = tmpbuffer; if (error) { if (showerror) { (showerror_cb)(_("GpgMe encrypt error"), gpgme_strerror(error)); } return 1; } else return 0; }
gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account, const gchar *from_addr) { GPGAccountConfig *config; const gchar *signer_addr = account->address; gpgme_signers_clear(ctx); if (from_addr) signer_addr = from_addr; config = prefs_gpg_account_get_config(account); switch(config->sign_key) { case SIGN_KEY_DEFAULT: debug_print("using default gnupg key\n"); break; case SIGN_KEY_BY_FROM: debug_print("using key for %s\n", signer_addr); break; case SIGN_KEY_CUSTOM: debug_print("using key for %s\n", config->sign_key_id); break; } if (config->sign_key != SIGN_KEY_DEFAULT) { const gchar *keyid; gpgme_key_t key, key2; gpgme_error_t err; if (config->sign_key == SIGN_KEY_BY_FROM) keyid = signer_addr; else if (config->sign_key == SIGN_KEY_CUSTOM) keyid = config->sign_key_id; else goto bail; err = gpgme_op_keylist_start(ctx, keyid, 1); if (!err) { do { err = gpgme_op_keylist_next(ctx, &key); if (!err && key && key->protocol == gpgme_get_protocol(ctx) && !key->expired && !key->revoked && !key->disabled) break; if (!err && key && key->protocol != gpgme_get_protocol(ctx)) { debug_print("skipping a key (wrong protocol %d)\n", key->protocol); gpgme_key_release(key); } if (!err && key && (key->expired || key->revoked || key->disabled)) { debug_print("skipping a key"); if (key->expired) debug_print(" expired"); if (key->revoked) debug_print(" revoked"); if (key->disabled) debug_print(" disabled"); debug_print("\n"); gpgme_key_release(key); } } while (!err); } if (err) { g_warning("setup_signers start: %s", gpgme_strerror(err)); privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err)); goto bail; } do { err = gpgme_op_keylist_next(ctx, &key2); if (!err && key2 && key2->protocol == gpgme_get_protocol(ctx) && !key2->expired && !key2->revoked && !key2->disabled) break; if (!err && key2 && key2->protocol != gpgme_get_protocol(ctx)) { debug_print("skipping a key (wrong protocol %d)\n", key2->protocol); gpgme_key_release(key2); } if (!err && key2 && (key2->expired || key2->revoked || key2->disabled)) { debug_print("skipping a key"); if (key2->expired) debug_print(" expired"); if (key2->revoked) debug_print(" revoked"); if (key2->disabled) debug_print(" disabled"); debug_print("\n"); gpgme_key_release(key2); } } while (!err); if (!err) { gpgme_key_release(key2); g_warning("ambiguous specification of secret key '%s'\n", keyid); privacy_set_error(_("Secret key specification is ambiguous")); goto bail; } gpgme_op_keylist_end(ctx); err = gpgme_signers_add(ctx, key); debug_print("got key (proto %d (pgp %d, smime %d).\n", key->protocol, GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_CMS); gpgme_key_release(key); if (err) { g_warning("error adding secret key: %s\n", gpgme_strerror(err)); privacy_set_error(_("Error setting secret key: %s"), gpgme_strerror(err)); goto bail; } } prefs_gpg_account_free_config(config); return TRUE; bail: prefs_gpg_account_free_config(config); return FALSE; }
gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account, const gchar *from_addr) { GPGAccountConfig *config; const gchar *signer_addr = account->address; gpgme_signers_clear(ctx); if (from_addr) signer_addr = from_addr; config = prefs_gpg_account_get_config(account); switch(config->sign_key) { case SIGN_KEY_DEFAULT: debug_print("using default gnupg key\n"); break; case SIGN_KEY_BY_FROM: debug_print("using key for %s\n", signer_addr); break; case SIGN_KEY_CUSTOM: debug_print("using key for %s\n", config->sign_key_id); break; } if (config->sign_key != SIGN_KEY_DEFAULT) { const gchar *keyid; gpgme_key_t key, found_key; gpgme_error_t err; if (config->sign_key == SIGN_KEY_BY_FROM) keyid = signer_addr; else if (config->sign_key == SIGN_KEY_CUSTOM) keyid = config->sign_key_id; else goto bail; found_key = NULL; /* Look for any key, not just private ones, or GPGMe doesn't * correctly set the revoked flag. */ err = gpgme_op_keylist_start(ctx, keyid, 0); while ((err = gpgme_op_keylist_next(ctx, &key)) == 0) { if (key == NULL) continue; if (!key->can_sign) continue; if (key->protocol != gpgme_get_protocol(ctx)) { debug_print("skipping a key (wrong protocol %d)\n", key->protocol); gpgme_key_release(key); continue; } if (key->expired) { debug_print("skipping a key, expired"); gpgme_key_release(key); continue; } if (key->revoked) { debug_print("skipping a key, revoked"); gpgme_key_release(key); continue; } if (key->disabled) { debug_print("skipping a key, disabled"); gpgme_key_release(key); continue; } if (found_key != NULL) { gpgme_key_release(key); gpgme_op_keylist_end(ctx); g_warning("ambiguous specification of secret key '%s'\n", keyid); privacy_set_error(_("Secret key specification is ambiguous")); goto bail; } found_key = key; } gpgme_op_keylist_end(ctx); if (found_key == NULL) { g_warning("setup_signers start: %s", gpgme_strerror(err)); privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err)); goto bail; } err = gpgme_signers_add(ctx, found_key); debug_print("got key (proto %d (pgp %d, smime %d).\n", found_key->protocol, GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_CMS); gpgme_key_release(found_key); if (err) { g_warning("error adding secret key: %s\n", gpgme_strerror(err)); privacy_set_error(_("Error setting secret key: %s"), gpgme_strerror(err)); goto bail; } } prefs_gpg_account_free_config(config); return TRUE; bail: prefs_gpg_account_free_config(config); return FALSE; }
char* p_gpg_sign(const char *const str, const char *const fp) { gpgme_ctx_t ctx; gpgme_error_t error = gpgme_new(&ctx); if (error) { log_error("GPG: Failed to create gpgme context. %s %s", gpgme_strsource(error), gpgme_strerror(error)); return NULL; } gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)_p_gpg_passphrase_cb, NULL); gpgme_key_t key = NULL; error = gpgme_get_key(ctx, fp, &key, 1); if (error || key == NULL) { log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_release(ctx); return NULL; } gpgme_signers_clear(ctx); error = gpgme_signers_add(ctx, key); gpgme_key_unref(key); if (error) { log_error("GPG: Failed to load signer. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_release(ctx); return NULL; } char *str_or_empty = NULL; if (str) { str_or_empty = strdup(str); } else { str_or_empty = strdup(""); } gpgme_data_t str_data; gpgme_data_new_from_mem(&str_data, str_or_empty, strlen(str_or_empty), 1); free(str_or_empty); gpgme_data_t signed_data; gpgme_data_new(&signed_data); gpgme_set_armor(ctx,1); error = gpgme_op_sign(ctx, str_data, signed_data, GPGME_SIG_MODE_DETACH); gpgme_data_release(str_data); gpgme_release(ctx); if (error) { log_error("GPG: Failed to sign string. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_data_release(signed_data); return NULL; } char *result = NULL; size_t len = 0; char *signed_str = gpgme_data_release_and_get_mem(signed_data, &len); if (signed_str) { GString *signed_gstr = g_string_new(""); g_string_append_len(signed_gstr, signed_str, len); result = _remove_header_footer(signed_gstr->str, PGP_SIGNATURE_FOOTER); g_string_free(signed_gstr, TRUE); gpgme_free(signed_str); } if (passphrase_attempt) { passphrase = strdup(passphrase_attempt); } return result; }