static GMimeSignatureList * pkcs7_verify (GMimeCryptoContext *context, GMimeDigestAlgo digest, GMimeStream *istream, GMimeStream *sigstream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; gpgme_data_t message, signature; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_error_t error; if ((error = gpgme_data_new_from_cbs (&message, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream")); return NULL; } /* if @sigstream is non-NULL, then it is a detached signature */ if (sigstream != NULL) { if ((error = gpgme_data_new_from_cbs (&signature, &pkcs7_stream_funcs, sigstream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open signature stream")); gpgme_data_release (message); return NULL; } } else { signature = NULL; } if ((error = gpgme_op_verify (pkcs7->ctx, signature, message, NULL)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify pkcs7 signature")); if (signature) gpgme_data_release (signature); gpgme_data_release (message); return NULL; } if (signature) gpgme_data_release (signature); if (message) gpgme_data_release (message); /* get/return the pkcs7 signatures */ return pkcs7_get_signatures (pkcs7, TRUE); #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return NULL; #endif /* ENABLE_SMIME */ }
static int pkcs7_sign (GMimeCryptoContext *context, const char *userid, GMimeDigestAlgo digest, GMimeStream *istream, GMimeStream *ostream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_sign_result_t result; gpgme_data_t input, output; gpgme_error_t error; if (!pkcs7_add_signer (pkcs7, userid, err)) return -1; gpgme_set_armor (pkcs7->ctx, FALSE); if ((error = gpgme_data_new_from_cbs (&input, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream")); return -1; } if ((error = gpgme_data_new_from_cbs (&output, &pkcs7_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream")); gpgme_data_release (input); return -1; } /* sign the input stream */ if ((error = gpgme_op_sign (pkcs7->ctx, input, output, GPGME_SIG_MODE_DETACH)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Signing failed")); gpgme_data_release (output); gpgme_data_release (input); return -1; } gpgme_data_release (output); gpgme_data_release (input); /* return the digest algorithm used for signing */ result = gpgme_op_sign_result (pkcs7->ctx); return pkcs7_digest_id (context, gpgme_hash_algo_name (result->signatures->hash_algo)); #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return -1; #endif /* ENABLE_SMIME */ }
gpgme_data_t seahorse_vfs_data_read_multi (const gchar **uris, GError **err) { gpgme_error_t gerr; gpgme_data_t data; GList *datas = NULL; const gchar **u; for (u = uris; *u; u++) { if(!(*u)[0]) continue; data = seahorse_vfs_data_create (*u, SEAHORSE_VFS_READ, err); if (!data) break; datas = g_list_prepend (datas, data); } /* Failed somewhere */ if (!data) { multi_data_release (datas); return NULL; } datas = g_list_reverse (datas); gerr = gpgme_data_new_from_cbs (&data, &multi_data_cbs, datas); if (!GPG_IS_OK (gerr)) { seahorse_util_gpgme_to_error (gerr, err); multi_data_release (datas); return NULL; } return data; }
/* Create a data on the given uri, remote uris get gnome-vfs backends, * local uris get normal file access. */ static gpgme_data_t create_vfs_data (GFile *file, guint mode, SeahorseVfsProgressCb progcb, gpointer userdata, gpg_error_t* err) { gpgme_error_t gerr; gpgme_data_t ret = NULL; VfsAsyncHandle* handle = NULL; if (!err) err = &gerr; handle = vfs_data_open (file, mode & SEAHORSE_VFS_WRITE, mode & SEAHORSE_VFS_DELAY); if (handle) { *err = gpgme_data_new_from_cbs (&ret, &vfs_data_cbs, handle); if (!GPG_IS_OK (*err)) { vfs_data_cbs.release (handle); ret = NULL; } handle->progcb = progcb; handle->userdata = userdata; handle->gdata = ret; } return ret; }
static int pkcs7_export_keys (GMimeCryptoContext *context, GPtrArray *keys, GMimeStream *ostream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_data_t keydata; gpgme_error_t error; guint i; if ((error = gpgme_data_new_from_cbs (&keydata, &pkcs7_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream")); return -1; } /* export the key(s) */ for (i = 0; i < keys->len; i++) { if ((error = gpgme_op_export (pkcs7->ctx, keys->pdata[i], 0, keydata)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not export key data")); gpgme_data_release (keydata); return -1; } } gpgme_data_release (keydata); return 0; #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return -1; #endif /* ENABLE_SMIME */ }
static int pkcs7_import_keys (GMimeCryptoContext *context, GMimeStream *istream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_data_t keydata; gpgme_error_t error; if ((error = gpgme_data_new_from_cbs (&keydata, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream")); return -1; } /* import the key(s) */ if ((error = gpgme_op_import (pkcs7->ctx, keydata)) != GPG_ERR_NO_ERROR) { //printf ("import error (%d): %s\n", error & GPG_ERR_CODE_MASK, gpg_strerror (error)); g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not import key data")); gpgme_data_release (keydata); return -1; } gpgme_data_release (keydata); return 0; #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return -1; #endif /* ENABLE_SMIME */ }
static GMimeDecryptResult * pkcs7_decrypt (GMimeCryptoContext *context, GMimeStream *istream, GMimeStream *ostream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; GMimeDecryptResult *result; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_decrypt_result_t res; gpgme_data_t input, output; gpgme_error_t error; if ((error = gpgme_data_new_from_cbs (&input, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream")); return NULL; } if ((error = gpgme_data_new_from_cbs (&output, &pkcs7_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream")); gpgme_data_release (input); return NULL; } /* decrypt the input stream */ if ((error = gpgme_op_decrypt_verify (pkcs7->ctx, input, output)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Decryption failed")); gpgme_data_release (output); gpgme_data_release (input); return NULL; } gpgme_data_release (output); gpgme_data_release (input); return pkcs7_get_decrypt_result (pkcs7); #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return NULL; #endif /* ENABLE_SMIME */ }
gpgme_data_t seahorse_gpgme_data_input (GInputStream* input) { gpgme_error_t gerr; gpgme_data_t ret = NULL; g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL); gerr = gpgme_data_new_from_cbs (&ret, &input_cbs, input); if (!GPG_IS_OK (gerr)) return NULL; g_object_ref (input); return ret; }
gpgme_data_t seahorse_gpgme_data_output (GOutputStream* output) { gpgme_error_t gerr; gpgme_data_t ret = NULL; g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), NULL); gerr = gpgme_data_new_from_cbs (&ret, &output_cbs, output); if (!GPG_IS_OK (gerr)) return NULL; g_object_ref (output); return ret; }
GpgME::Data::Data( DataProvider * dp ) { d = new Private(); d->ref(); if ( !dp ) return; if ( !dp->isSupported( DataProvider::Read ) ) d->cbs.read = 0; if ( !dp->isSupported( DataProvider::Write ) ) d->cbs.write = 0; if ( !dp->isSupported( DataProvider::Seek ) ) d->cbs.seek = 0; if ( !dp->isSupported( DataProvider::Release ) ) d->cbs.release = 0; const gpgme_error_t e = gpgme_data_new_from_cbs( &d->data, &d->cbs, dp ); if ( e ) d->data = 0; #ifndef NDEBUG std::cerr << "GpgME::Data(): DataProvider supports: " << ( d->cbs.read ? "read" : "no read" ) << ", " << ( d->cbs.write ? "write" : "no write" ) << ", " << ( d->cbs.seek ? "seek" : "no seek" ) << ", " << ( d->cbs.release ? "release" : "no release" ) << std::endl; #endif }
/** \brief Decrypt data * * \param istream GMime input (encrypted) stream. * \param ostream GMime output (decrypted) stream. * \param protocol GpgME crypto protocol to use. * \param parent Parent window to be passed to the passphrase callback * function. * \param error Filled with error information on error. * \return A new signature status object on success, or NULL on error. * * Decrypt and -if applicable- verify the signature of the passed data * stream. If the input is not signed the returned signature status will * be GPG_ERR_NOT_SIGNED. */ GMimeGpgmeSigstat * libbalsa_gpgme_decrypt(GMimeStream * crypted, GMimeStream * plain, gpgme_protocol_t protocol, GtkWindow * parent, GError ** error) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t plain_data; gpgme_data_t crypt_data; GMimeGpgmeSigstat *result; struct gpgme_data_cbs cbs = { (gpgme_data_read_cb_t) g_mime_gpgme_stream_rd, /* read method */ (gpgme_data_write_cb_t) g_mime_gpgme_stream_wr, /* write method */ NULL, /* seek method */ cb_data_release /* release method */ }; /* paranoia checks */ g_return_val_if_fail(GMIME_IS_STREAM(crypted), NULL); g_return_val_if_fail(GMIME_IS_STREAM(plain), NULL); g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP || protocol == GPGME_PROTOCOL_CMS, NULL); /* create the GpgME context */ if ((err = gpgme_new_with_protocol(&ctx, protocol, parent, error)) != GPG_ERR_NO_ERROR) return NULL; /* create the data streams */ if ((err = gpgme_data_new_from_cbs(&crypt_data, &cbs, crypted)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not get data from stream")); gpgme_release(ctx); return NULL; } if ((err = gpgme_data_new_from_cbs(&plain_data, &cbs, plain)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not create new data object")); gpgme_data_release(crypt_data); gpgme_release(ctx); return NULL; } /* try to decrypt */ if ((err = gpgme_op_decrypt_verify(ctx, crypt_data, plain_data)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("decryption failed")); result = NULL; } else { /* decryption successful, check for signature */ result = g_mime_gpgme_sigstat_new_from_gpgme_ctx(ctx); } /* clean up */ gpgme_data_release(plain_data); gpgme_data_release(crypt_data); gpgme_release(ctx); return result; }
/** \brief Encrypt data * * \param recipients Array of User ID for which the matter shall be * encrypted using their public keys. * \param sign_for User ID of the signer or NULL if the matter shall not be * signed. Note that combined signing and encryption is allowed \em * only in OpenPGP single-part (i.e. RFC 2440) mode. * \param istream GMime input stream. * \param ostream GMime output stream. * \param protocol GpgME crypto protocol to use for encryption. * \param singlepart_mode TRUE indicates single-part mode (integrated * signature), FALSE a detached signature. * \param trust_all_keys TRUE if all low-truct keys shall be accepted for * encryption. Otherwise, the function will use the global callback * to ask the user whether a low-trust key shall be accepted. * \param parent Parent window to be passed to the callback functions. * \param error Filled with error information on error. * \return 0 on success, or -1 on error. * * Encrypt the passed matter and write the result to the output stream. * Combined signing and encryption is allowed for single-part OpenPGP mode * only. */ int libbalsa_gpgme_encrypt(GPtrArray * recipients, const char *sign_for, GMimeStream * istream, GMimeStream * ostream, gpgme_protocol_t protocol, gboolean singlepart_mode, gboolean trust_all_keys, GtkWindow * parent, GError ** error) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_key_t *rcpt_keys; gpgme_data_t plain; gpgme_data_t crypt; struct gpgme_data_cbs cbs = { (gpgme_data_read_cb_t) g_mime_gpgme_stream_rd, /* read method */ (gpgme_data_write_cb_t) g_mime_gpgme_stream_wr, /* write method */ NULL, /* seek method */ cb_data_release /* release method */ }; /* paranoia checks */ g_return_val_if_fail(recipients != NULL, -1); g_return_val_if_fail(GMIME_IS_STREAM(istream), -1); g_return_val_if_fail(GMIME_IS_STREAM(ostream), GPGME_MD_NONE); g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP || protocol == GPGME_PROTOCOL_CMS, -1); /* create the GpgME context */ if ((err = gpgme_new_with_protocol(&ctx, protocol, parent, error)) != GPG_ERR_NO_ERROR) return -1; /* sign & encrypt is valid only for single-part OpenPGP */ if (sign_for != NULL && (!singlepart_mode || protocol != GPGME_PROTOCOL_OpenPGP)) { if (error) g_set_error(error, GPGME_ERROR_QUARK, GPG_ERR_INV_ENGINE, _ ("combined signing and encryption is defined only for RFC 2440")); gpgme_release(ctx); return -1; } /* if requested, find the secret key for "userid" */ if (sign_for && !gpgme_add_signer(ctx, sign_for, parent, error)) { gpgme_release(ctx); return -1; } /* build the list of recipients */ if (! (rcpt_keys = gpgme_build_recipients(ctx, recipients, trust_all_keys, parent, error))) { gpgme_release(ctx); return -1; } /* create the data objects */ if (protocol == GPGME_PROTOCOL_OpenPGP) { gpgme_set_armor(ctx, 1); gpgme_set_textmode(ctx, singlepart_mode); } else { gpgme_set_armor(ctx, 0); gpgme_set_textmode(ctx, 0); } if ((err = gpgme_data_new_from_cbs(&plain, &cbs, istream)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not get data from stream")); release_keylist(rcpt_keys); gpgme_release(ctx); return -1; } if ((err = gpgme_data_new_from_cbs(&crypt, &cbs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not create new data object")); release_keylist(rcpt_keys); gpgme_data_release(plain); gpgme_release(ctx); return -1; } /* do the encrypt or sign and encrypt operation * Note: we set "always trust" here, as if we detected an untrusted key * earlier, the user already accepted it */ if (sign_for) err = gpgme_op_encrypt_sign(ctx, rcpt_keys, GPGME_ENCRYPT_ALWAYS_TRUST, plain, crypt); else err = gpgme_op_encrypt(ctx, rcpt_keys, GPGME_ENCRYPT_ALWAYS_TRUST, plain, crypt); release_keylist(rcpt_keys); gpgme_data_release(plain); gpgme_data_release(crypt); gpgme_release(ctx); if (err != GPG_ERR_NO_ERROR) { if (sign_for) g_set_error_from_gpgme(error, err, _("signing and encryption failed")); else g_set_error_from_gpgme(error, err, _("encryption failed")); return -1; } else return 0; }
/** \brief Sign data * * \param userid User ID of the signer. * \param istream GMime input stream. * \param ostream GMime output stream. * \param protocol GpgME crypto protocol of the signature. * \param singlepart_mode TRUE indicates single-part mode (integrated * signature), FALSE a detached signature. * \param parent Parent window to be passed to the passphrase callback * function. * \param error Filled with error information on error. * \return The hash algorithm used for creating the signature, or * GPGME_MD_NONE on error. * * Sign the passed matter and write the detached signature or the signed * input and the signature, respectively, to the output stream. The global * callback to read the passphrase for the user's private key will be * called by GpgME if no GPG Agent is running. */ gpgme_hash_algo_t libbalsa_gpgme_sign(const gchar * userid, GMimeStream * istream, GMimeStream * ostream, gpgme_protocol_t protocol, gboolean singlepart_mode, GtkWindow * parent, GError ** error) { gpgme_error_t err; gpgme_ctx_t ctx; gpgme_sig_mode_t sig_mode; gpgme_data_t in; gpgme_data_t out; gpgme_hash_algo_t hash_algo; struct gpgme_data_cbs cbs = { (gpgme_data_read_cb_t) g_mime_gpgme_stream_rd, /* read method */ (gpgme_data_write_cb_t) g_mime_gpgme_stream_wr, /* write method */ NULL, /* seek method */ cb_data_release /* release method */ }; /* paranoia checks */ g_return_val_if_fail(GMIME_IS_STREAM(istream), GPGME_MD_NONE); g_return_val_if_fail(GMIME_IS_STREAM(ostream), GPGME_MD_NONE); g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP || protocol == GPGME_PROTOCOL_CMS, GPGME_MD_NONE); /* create the GpgME context */ if ((err = gpgme_new_with_protocol(&ctx, protocol, parent, error)) != GPG_ERR_NO_ERROR) return GPGME_MD_NONE; /* set the signature mode */ if (singlepart_mode) { if (protocol == GPGME_PROTOCOL_OpenPGP) sig_mode = GPGME_SIG_MODE_CLEAR; else sig_mode = GPGME_SIG_MODE_NORMAL; } else sig_mode = GPGME_SIG_MODE_DETACH; /* find the secret key for the "sign_for" address */ if (!gpgme_add_signer(ctx, userid, parent, error)) { gpgme_release(ctx); return GPGME_MD_NONE; } /* OpenPGP signatures are ASCII armored */ gpgme_set_armor(ctx, protocol == GPGME_PROTOCOL_OpenPGP); /* create gpgme data objects */ if ((err = gpgme_data_new_from_cbs(&in, &cbs, istream)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not get data from stream")); gpgme_release(ctx); return GPGME_MD_NONE; } if ((err = gpgme_data_new_from_cbs(&out, &cbs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not create new data object")); gpgme_data_release(in); gpgme_release(ctx); return GPGME_MD_NONE; } /* sign and get the used hash algorithm */ err = gpgme_op_sign(ctx, in, out, sig_mode); if (err != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("signing failed")); hash_algo = GPGME_MD_NONE; } else hash_algo = gpgme_op_sign_result(ctx)->signatures->hash_algo; /* clean up */ gpgme_data_release(in); gpgme_data_release(out); gpgme_release(ctx); return hash_algo; }
/** \brief Verify a signature * * \param content GMime stream of the signed matter. * \param sig_plain GMime signature stream for a detached signature, or the * output stream for the checked matter in single-part mode. * \param protocol GpgME crypto protocol of the signature. * \param singlepart_mode TRUE indicates single-part mode (i.e. sig_plain * an output stream). * \param error Filled with error information on error. * \return A new signature status object on success, or NULL on error. * * Verify a signature by calling GpgME on the passed streams, and create a * new signature object on success. */ GMimeGpgmeSigstat * libbalsa_gpgme_verify(GMimeStream * content, GMimeStream * sig_plain, gpgme_protocol_t protocol, gboolean singlepart_mode, GError ** error) { gpgme_error_t err; gpgme_ctx_t ctx; struct gpgme_data_cbs cbs = { (gpgme_data_read_cb_t) g_mime_gpgme_stream_rd, /* read method */ (gpgme_data_write_cb_t) g_mime_gpgme_stream_wr, /* write method */ NULL, /* seek method */ cb_data_release /* release method */ }; gpgme_data_t cont_data; gpgme_data_t sig_plain_data; GMimeGpgmeSigstat *result; /* paranoia checks */ g_return_val_if_fail(GMIME_IS_STREAM(content), NULL); g_return_val_if_fail(GMIME_IS_STREAM(sig_plain), NULL); g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP || protocol == GPGME_PROTOCOL_CMS, NULL); /* create the GpgME context */ if ((err = gpgme_new_with_protocol(&ctx, protocol, NULL, error)) != GPG_ERR_NO_ERROR) return NULL; /* create the message stream */ if ((err = gpgme_data_new_from_cbs(&cont_data, &cbs, content)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not get data from stream")); gpgme_release(ctx); return NULL; } /* create data object for the detached signature stream or the * "decrypted" plaintext */ if ((err = gpgme_data_new_from_cbs(&sig_plain_data, &cbs, sig_plain)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not get data from stream")); gpgme_data_release(cont_data); gpgme_release(ctx); return NULL; } /* verify the signature */ if (singlepart_mode) err = gpgme_op_verify(ctx, cont_data, NULL, sig_plain_data); else err = gpgme_op_verify(ctx, sig_plain_data, cont_data, NULL); if (err != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("signature verification failed")); result = g_mime_gpgme_sigstat_new(); result->status = err; result->protocol = gpgme_get_protocol(ctx); } else result = g_mime_gpgme_sigstat_new_from_gpgme_ctx(ctx); /* release gmgme data buffers, destroy the context and return the * signature object */ gpgme_data_release(cont_data); gpgme_data_release(sig_plain_data); gpgme_release(ctx); return result; }
int main (int argc, char *argv[]) { gpgme_ctx_t ctx; gpgme_error_t err; struct gpgme_data_cbs cbs; gpgme_data_t in, out; gpgme_key_t key[3] = { NULL, NULL, NULL }; gpgme_encrypt_result_t result; size_t nbytes; struct cb_parms parms; if (argc > 1) nbytes = atoi (argv[1]); else nbytes = 100000; init_gpgme (GPGME_PROTOCOL_OpenPGP); memset (&cbs, 0, sizeof cbs); cbs.read = read_cb; cbs.write = write_cb; memset (&parms, 0, sizeof parms); parms.bytes_to_send = nbytes; err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_armor (ctx, 0); /* Install a progress handler to enforce a bit of more work to the gpgme i/o system. */ gpgme_set_progress_cb (ctx, progress_cb, NULL); err = gpgme_data_new_from_cbs (&in, &cbs, &parms); fail_if_err (err); err = gpgme_data_new_from_cbs (&out, &cbs, &parms); fail_if_err (err); err = gpgme_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", &key[0], 0); fail_if_err (err); err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", &key[1], 0); fail_if_err (err); err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); fail_if_err (err); result = gpgme_op_encrypt_result (ctx); if (result->invalid_recipients) { fprintf (stderr, "Invalid recipient encountered: %s\n", result->invalid_recipients->fpr); exit (1); } printf ("plaintext=%u bytes, ciphertext=%u bytes\n", (unsigned int)nbytes, (unsigned int)parms.bytes_received); gpgme_key_unref (key[0]); gpgme_key_unref (key[1]); gpgme_data_release (in); gpgme_data_release (out); gpgme_release (ctx); return 0; }
static int pkcs7_encrypt (GMimeCryptoContext *context, gboolean sign, const char *userid, GMimeDigestAlgo digest, GPtrArray *recipients, GMimeStream *istream, GMimeStream *ostream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_data_t input, output; gpgme_error_t error; gpgme_key_t *rcpts; gpgme_key_t key; guint i; if (sign) { g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("Cannot sign and encrypt a stream at the same time using pkcs7")); return -1; } /* create an array of recipient keys for GpgMe */ rcpts = g_new0 (gpgme_key_t, recipients->len + 1); for (i = 0; i < recipients->len; i++) { if (!(key = pkcs7_get_key_by_name (pkcs7, recipients->pdata[i], FALSE, err))) { key_list_free (rcpts); return -1; } rcpts[i] = key; } if ((error = gpgme_data_new_from_cbs (&input, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream")); key_list_free (rcpts); return -1; } if ((error = gpgme_data_new_from_cbs (&output, &pkcs7_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream")); gpgme_data_release (input); key_list_free (rcpts); return -1; } /* encrypt the input stream */ error = gpgme_op_encrypt (pkcs7->ctx, rcpts, GPGME_ENCRYPT_ALWAYS_TRUST, input, output); gpgme_data_release (output); gpgme_data_release (input); key_list_free (rcpts); if (error != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Encryption failed")); return -1; } return 0; #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return -1; #endif /* ENABLE_SMIME */ }