[gmime] Share code between gpg and pkcs7 contexts



commit e5a8f5c16a824b9b8d5760c98697f2dcc9929f75
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Fri Mar 10 13:11:38 2017 -0500

    Share code between gpg and pkcs7 contexts

 gmime/gmime-gpg-context.c   |  275 +--------------------------------
 gmime/gmime-gpgme-utils.c   |  316 ++++++++++++++++++++++++++++++++++++-
 gmime/gmime-gpgme-utils.h   |   18 ++-
 gmime/gmime-pkcs7-context.c |  363 +------------------------------------------
 tests/test-pgpmime.c        |   13 ++-
 5 files changed, 345 insertions(+), 640 deletions(-)
---
diff --git a/gmime/gmime-gpg-context.c b/gmime/gmime-gpg-context.c
index 29de2e4..0f453f2 100644
--- a/gmime/gmime-gpg-context.c
+++ b/gmime/gmime-gpg-context.c
@@ -266,49 +266,6 @@ gpg_get_key_exchange_protocol (GMimeCryptoContext *ctx)
        return "application/pgp-keys";
 }
 
-#ifdef ENABLE_CRYPTO
-static ssize_t
-gpg_stream_read (void *stream, void *buffer, size_t size)
-{
-       return g_mime_stream_read ((GMimeStream *) stream, (char *) buffer, size);
-}
-
-static ssize_t
-gpg_stream_write (void *stream, const void *buffer, size_t size)
-{
-       return g_mime_stream_write ((GMimeStream *) stream, (const char *) buffer, size);
-}
-
-static off_t
-gpg_stream_seek (void *stream, off_t offset, int whence)
-{
-       switch (whence) {
-       case SEEK_SET:
-               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_SET);
-       case SEEK_CUR:
-               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_CUR);
-       case SEEK_END:
-               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_END);
-       default:
-               return -1;
-       }
-}
-
-static void
-gpg_stream_free (void *stream)
-{
-       /* no-op */
-}
-
-static struct gpgme_data_cbs gpg_stream_funcs = {
-       gpg_stream_read,
-       gpg_stream_write,
-       gpg_stream_seek,
-       gpg_stream_free
-};
-
-#endif /* ENABLE_CRYPTO */
-
 static int
 gpg_sign (GMimeCryptoContext *context, gboolean detach, const char *userid, GMimeDigestAlgo digest,
          GMimeStream *istream, GMimeStream *ostream, GError **err)
@@ -316,45 +273,10 @@ gpg_sign (GMimeCryptoContext *context, gboolean detach, const char *userid, GMim
 #ifdef ENABLE_CRYPTO
        gpgme_sig_mode_t mode = detach ? GPGME_SIG_MODE_DETACH : GPGME_SIG_MODE_CLEAR;
        GMimeGpgContext *gpg = (GMimeGpgContext *) context;
-       gpgme_sign_result_t result;
-       gpgme_data_t input, output;
-       gpgme_error_t error;
-       
-       if (!g_mime_gpgme_add_signer (gpg->ctx, userid, err))
-               return -1;
-       
-       if ((error = gpgme_data_new_from_cbs (&input, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-               gpgme_signers_clear (gpg->ctx);
-               return -1;
-       }
-       
-       if ((error = gpgme_data_new_from_cbs (&output, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
-               gpgme_signers_clear (gpg->ctx);
-               gpgme_data_release (input);
-               return -1;
-       }
        
        gpgme_set_textmode (gpg->ctx, !detach);
        
-       /* sign the input stream */
-       if ((error = gpgme_op_sign (gpg->ctx, input, output, mode)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Signing failed: %s"), gpgme_strerror (error));
-               gpgme_signers_clear (gpg->ctx);
-               gpgme_data_release (output);
-               gpgme_data_release (input);
-               return -1;
-       }
-       
-       gpgme_signers_clear (gpg->ctx);
-       gpgme_data_release (output);
-       gpgme_data_release (input);
-       
-       /* return the digest algorithm used for signing */
-       result = gpgme_op_sign_result (gpg->ctx);
-       
-       return (GMimeDigestAlgo) result->signatures->hash_algo;
+       return g_mime_gpgme_sign (gpg->ctx, mode, userid, digest, istream, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("PGP support is not enabled in 
this build"));
        
@@ -368,56 +290,8 @@ gpg_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeStream *is
 {
 #ifdef ENABLE_CRYPTO
        GMimeGpgContext *gpg = (GMimeGpgContext *) context;
-       gpgme_data_t sig, signed_text, plain;
-       gpgme_error_t error;
-       
-       if (sigstream != NULL) {
-               /* if @sigstream is non-NULL, then it is a detached signature */
-               if ((error = gpgme_data_new_from_cbs (&signed_text, &gpg_stream_funcs, istream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-                       return NULL;
-               }
-               
-               if ((error = gpgme_data_new_from_cbs (&sig, &gpg_stream_funcs, sigstream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open signature stream: %s"), 
gpgme_strerror (error));
-                       gpgme_data_release (signed_text);
-                       return NULL;
-               }
-               
-               plain = NULL;
-       } else if (ostream != NULL) {
-               /* if @ostream is non-NULL, then we are expected to write the extracted plaintext to it */
-               if ((error = gpgme_data_new_from_cbs (&sig, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) 
{
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-                       return NULL;
-               }
-               
-               if ((error = gpgme_data_new_from_cbs (&plain, &gpg_stream_funcs, ostream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
-                       gpgme_data_release (sig);
-                       return NULL;
-               }
-               
-               signed_text = NULL;
-       } else {
-               g_set_error_literal (err, GMIME_GPGME_ERROR, error, _("Missing signature stream or output 
stream"));
-               return NULL;
-       }
        
-       error = gpgme_op_verify (gpg->ctx, sig, signed_text, plain);
-       if (signed_text)
-               gpgme_data_release (signed_text);
-       if (plain)
-               gpgme_data_release (plain);
-       gpgme_data_release (sig);
-       
-       if (error != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify gpg signature: %s"), 
gpgme_strerror (error));
-               return NULL;
-       }
-       
-       /* get/return the gpg signatures */
-       return g_mime_gpgme_get_signatures (gpg->ctx, TRUE);
+       return g_mime_gpgme_verify (gpg->ctx, flags, istream, sigstream, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("PGP support is not enabled in 
this build"));
        
@@ -432,66 +306,8 @@ gpg_encrypt (GMimeCryptoContext *context, gboolean sign, const char *userid, GMi
 {
 #ifdef ENABLE_CRYPTO
        GMimeGpgContext *gpg = (GMimeGpgContext *) context;
-       gpgme_encrypt_flags_t encrypt_flags = 0;
-       gpgme_data_t input, output;
-       gpgme_error_t error;
-       gpgme_key_t *rcpts;
-       gpgme_key_t key;
-       guint i;
-       
-       if (flags & GMIME_ENCRYPT_FLAGS_ALWAYS_TRUST)
-               encrypt_flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
        
-       /* 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 = g_mime_gpgme_get_key_by_name (gpg->ctx, recipients->pdata[i], FALSE, err))) {
-                       g_mime_gpgme_keylist_free (rcpts);
-                       return -1;
-               }
-               
-               rcpts[i] = key;
-       }
-       
-       if ((error = gpgme_data_new_from_cbs (&input, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-               g_mime_gpgme_keylist_free (rcpts);
-               return -1;
-       }
-       
-       if ((error = gpgme_data_new_from_cbs (&output, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
-               g_mime_gpgme_keylist_free (rcpts);
-               gpgme_data_release (input);
-               return -1;
-       }
-       
-       /* encrypt the input stream */
-       if (sign) {
-               if (!g_mime_gpgme_add_signer (gpg->ctx, userid, err)) {
-                       g_mime_gpgme_keylist_free (rcpts);
-                       gpgme_data_release (output);
-                       gpgme_data_release (input);
-                       return -1;
-               }
-               
-               error = gpgme_op_encrypt_sign (gpg->ctx, rcpts, encrypt_flags, input, output);
-               
-               gpgme_signers_clear (gpg->ctx);
-       } else {
-               error = gpgme_op_encrypt (gpg->ctx, rcpts, encrypt_flags, input, output);
-       }
-       
-       g_mime_gpgme_keylist_free (rcpts);
-       gpgme_data_release (output);
-       gpgme_data_release (input);
-       
-       if (error != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Encryption failed: %s"), gpgme_strerror 
(error));
-               return -1;
-       }
-       
-       return 0;
+       return g_mime_gpgme_encrypt (gpg->ctx, sign, userid, digest, flags, recipients, istream, ostream, 
err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("PGP support is not enabled in 
this build"));
        
@@ -505,53 +321,8 @@ gpg_decrypt (GMimeCryptoContext *context, GMimeDecryptFlags flags, const char *s
 {
 #ifdef ENABLE_CRYPTO
        GMimeGpgContext *gpg = (GMimeGpgContext *) context;
-       GMimeDecryptResult *result;
-       gpgme_decrypt_result_t res;
-       gpgme_data_t input, output;
-       gpgme_error_t error;
-       
-       if ((error = gpgme_data_new_from_cbs (&input, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-               return NULL;
-       }
-       
-       if ((error = gpgme_data_new_from_cbs (&output, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
-               gpgme_data_release (input);
-               return NULL;
-       }
-       
-       if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
-               gpgme_set_ctx_flag (gpg->ctx, "export-session-key", "1");
        
-       if (session_key)
-               gpgme_set_ctx_flag (gpg->ctx, "override-session-key", session_key);
-       
-       /* decrypt the input stream */
-       if ((error = gpgme_op_decrypt_verify (gpg->ctx, input, output)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Decryption failed: %s"), gpgme_strerror 
(error));
-               
-               if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
-                       gpgme_set_ctx_flag (gpg->ctx, "export-session-key", "0");
-               
-               if (session_key)
-                       gpgme_set_ctx_flag (gpg->ctx, "override-session-key", NULL);
-               
-               gpgme_data_release (output);
-               gpgme_data_release (input);
-               return NULL;
-       }
-       
-       if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
-               gpgme_set_ctx_flag (gpg->ctx, "export-session-key", "0");
-       
-       if (session_key)
-               gpgme_set_ctx_flag (gpg->ctx, "override-session-key", NULL);
-       
-       gpgme_data_release (output);
-       gpgme_data_release (input);
-       
-       return g_mime_gpgme_get_decrypt_result (gpg->ctx);
+       return g_mime_gpgme_decrypt (gpg->ctx, flags, session_key, istream, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("PGP support is not enabled in 
this build"));
        
@@ -564,25 +335,8 @@ gpg_import_keys (GMimeCryptoContext *context, GMimeStream *istream, GError **err
 {
 #ifdef ENABLE_CRYPTO
        GMimeGpgContext *gpg = (GMimeGpgContext *) context;
-       gpgme_data_t keydata;
-       gpgme_error_t error;
        
-       if ((error = gpgme_data_new_from_cbs (&keydata, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-               return -1;
-       }
-       
-       /* import the key(s) */
-       if ((error = gpgme_op_import (gpg->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: %s"), 
gpgme_strerror (error));
-               gpgme_data_release (keydata);
-               return -1;
-       }
-       
-       gpgme_data_release (keydata);
-       
-       return 0;
+       return g_mime_gpgme_import (gpg->ctx, istream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("PGP support is not enabled in 
this build"));
        
@@ -595,25 +349,8 @@ gpg_export_keys (GMimeCryptoContext *context, const char *keys[], GMimeStream *o
 {
 #ifdef ENABLE_CRYPTO
        GMimeGpgContext *gpg = (GMimeGpgContext *) context;
-       gpgme_data_t keydata;
-       gpgme_error_t error;
-       guint i;
-       
-       if ((error = gpgme_data_new_from_cbs (&keydata, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
-               return -1;
-       }
-       
-       /* export the key(s) */
-       if ((error = gpgme_op_export_ext (gpg->ctx, keys, 0, keydata)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not export key data: %s"), 
gpgme_strerror (error));
-               gpgme_data_release (keydata);
-               return -1;
-       }
-       
-       gpgme_data_release (keydata);
        
-       return 0;
+       return g_mime_gpgme_export (gpg->ctx, keys, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("PGP support is not enabled in 
this build"));
        
diff --git a/gmime/gmime-gpgme-utils.c b/gmime/gmime-gpgme-utils.c
index 9a7c208..964aea3 100644
--- a/gmime/gmime-gpgme-utils.c
+++ b/gmime/gmime-gpgme-utils.c
@@ -32,6 +32,46 @@
 
 #define _(x) x
 
+static ssize_t
+g_mime_gpgme_stream_read (void *stream, void *buffer, size_t size)
+{
+       return g_mime_stream_read ((GMimeStream *) stream, (char *) buffer, size);
+}
+
+static ssize_t
+g_mime_gpgme_stream_write (void *stream, const void *buffer, size_t size)
+{
+       return g_mime_stream_write ((GMimeStream *) stream, (const char *) buffer, size);
+}
+
+static off_t
+g_mime_gpgme_stream_seek (void *stream, off_t offset, int whence)
+{
+       switch (whence) {
+       case SEEK_SET:
+               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_SET);
+       case SEEK_CUR:
+               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_CUR);
+       case SEEK_END:
+               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_END);
+       default:
+               return -1;
+       }
+}
+
+static void
+g_mime_gpgme_stream_free (void *stream)
+{
+       /* no-op */
+}
+
+static struct gpgme_data_cbs gpg_stream_funcs = {
+       g_mime_gpgme_stream_read,
+       g_mime_gpgme_stream_write,
+       g_mime_gpgme_stream_seek,
+       g_mime_gpgme_stream_free
+};
+
 gpgme_error_t
 g_mime_gpgme_passphrase_callback (void *hook, const char *uid_hint, const char *passphrase_info, int 
prev_was_bad, int fd)
 {
@@ -63,7 +103,7 @@ g_mime_gpgme_passphrase_callback (void *hook, const char *uid_hint, const char *
 #define KEY_IS_OK(k)   (!((k)->expired || (k)->revoked ||      \
                           (k)->disabled || (k)->invalid))
 
-gpgme_key_t
+static gpgme_key_t
 g_mime_gpgme_get_key_by_name (gpgme_ctx_t ctx, const char *name, gboolean secret, GError **err)
 {
        time_t now = time (NULL);
@@ -146,7 +186,7 @@ g_mime_gpgme_get_key_by_name (gpgme_ctx_t ctx, const char *name, gboolean secret
        return key;
 }
 
-gboolean
+static gboolean
 g_mime_gpgme_add_signer (gpgme_ctx_t ctx, const char *signer, GError **err)
 {
        gpgme_key_t key = NULL;
@@ -166,6 +206,47 @@ g_mime_gpgme_add_signer (gpgme_ctx_t ctx, const char *signer, GError **err)
        return TRUE;
 }
 
+int
+g_mime_gpgme_sign (gpgme_ctx_t ctx, gpgme_sig_mode_t mode, const char *userid, GMimeDigestAlgo digest,
+                  GMimeStream *istream, GMimeStream *ostream, GError **err)
+{
+       gpgme_sign_result_t result;
+       gpgme_data_t input, output;
+       gpgme_error_t error;
+       
+       if (!g_mime_gpgme_add_signer (ctx, userid, err))
+               return -1;
+       
+       if ((error = gpgme_data_new_from_cbs (&input, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
+               gpgme_signers_clear (ctx);
+               return -1;
+       }
+       
+       if ((error = gpgme_data_new_from_cbs (&output, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
+               gpgme_data_release (input);
+               gpgme_signers_clear (ctx);
+               return -1;
+       }
+       
+       /* sign the input stream */
+       error = gpgme_op_sign (ctx, input, output, mode);
+       gpgme_data_release (output);
+       gpgme_data_release (input);
+       gpgme_signers_clear (ctx);
+       
+       if (error != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Signing failed: %s"), gpgme_strerror (error));
+               return -1;
+       }
+       
+       /* return the digest algorithm used for signing */
+       result = gpgme_op_sign_result (ctx);
+       
+       return (GMimeDigestAlgo) result->signatures->hash_algo;
+}
+
 static GMimeCertificateTrust
 get_trust (gpgme_validity_t trust)
 {
@@ -186,7 +267,7 @@ get_trust (gpgme_validity_t trust)
        }
 }
 
-GMimeSignatureList *
+static GMimeSignatureList *
 g_mime_gpgme_get_signatures (gpgme_ctx_t ctx, gboolean verify)
 {
        GMimeSignatureList *signatures;
@@ -265,7 +346,63 @@ g_mime_gpgme_get_signatures (gpgme_ctx_t ctx, gboolean verify)
        return signatures;
 }
 
-void
+GMimeSignatureList *
+g_mime_gpgme_verify (gpgme_ctx_t ctx, GMimeVerifyFlags flags, GMimeStream *istream, GMimeStream *sigstream,
+                    GMimeStream *ostream, GError **err)
+{
+       gpgme_data_t sig, signed_text, plain;
+       gpgme_error_t error;
+       
+       if (sigstream != NULL) {
+               /* if @sigstream is non-NULL, then it is a detached signature */
+               if ((error = gpgme_data_new_from_cbs (&signed_text, &gpg_stream_funcs, istream)) != 
GPG_ERR_NO_ERROR) {
+                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
+                       return NULL;
+               }
+               
+               if ((error = gpgme_data_new_from_cbs (&sig, &gpg_stream_funcs, sigstream)) != 
GPG_ERR_NO_ERROR) {
+                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open signature stream: %s"), 
gpgme_strerror (error));
+                       gpgme_data_release (signed_text);
+                       return NULL;
+               }
+               
+               plain = NULL;
+       } else if (ostream != NULL) {
+               /* if @ostream is non-NULL, then we are expected to write the extracted plaintext to it */
+               if ((error = gpgme_data_new_from_cbs (&sig, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) 
{
+                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
+                       return NULL;
+               }
+               
+               if ((error = gpgme_data_new_from_cbs (&plain, &gpg_stream_funcs, ostream)) != 
GPG_ERR_NO_ERROR) {
+                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
+                       gpgme_data_release (sig);
+                       return NULL;
+               }
+               
+               signed_text = NULL;
+       } else {
+               g_set_error_literal (err, GMIME_GPGME_ERROR, error, _("Missing signature stream or output 
stream"));
+               return NULL;
+       }
+       
+       error = gpgme_op_verify (ctx, sig, signed_text, plain);
+       if (signed_text)
+               gpgme_data_release (signed_text);
+       if (plain)
+               gpgme_data_release (plain);
+       gpgme_data_release (sig);
+       
+       if (error != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify signature: %s"), 
gpgme_strerror (error));
+               return NULL;
+       }
+       
+       /* get/return the signatures */
+       return g_mime_gpgme_get_signatures (ctx, TRUE);
+}
+
+static void
 g_mime_gpgme_keylist_free (gpgme_key_t *keys)
 {
        gpgme_key_t *key = keys;
@@ -278,7 +415,74 @@ g_mime_gpgme_keylist_free (gpgme_key_t *keys)
        g_free (keys);
 }
 
-GMimeDecryptResult *
+int
+g_mime_gpgme_encrypt (gpgme_ctx_t ctx, gboolean sign, const char *userid, GMimeDigestAlgo digest,
+                     GMimeEncryptFlags flags, GPtrArray *recipients, GMimeStream *istream, GMimeStream 
*ostream,
+                     GError **err)
+{
+       gpgme_encrypt_flags_t encrypt_flags = 0;
+       gpgme_data_t input, output;
+       gpgme_error_t error;
+       gpgme_key_t *rcpts;
+       gpgme_key_t key;
+       guint i;
+       
+       if (flags & GMIME_ENCRYPT_FLAGS_ALWAYS_TRUST)
+               encrypt_flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
+       
+       /* 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 = g_mime_gpgme_get_key_by_name (ctx, recipients->pdata[i], FALSE, err))) {
+                       g_mime_gpgme_keylist_free (rcpts);
+                       return -1;
+               }
+               
+               rcpts[i] = key;
+       }
+       
+       if ((error = gpgme_data_new_from_cbs (&input, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
+               g_mime_gpgme_keylist_free (rcpts);
+               return -1;
+       }
+       
+       if ((error = gpgme_data_new_from_cbs (&output, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
+               g_mime_gpgme_keylist_free (rcpts);
+               gpgme_data_release (input);
+               return -1;
+       }
+       
+       /* encrypt the input stream */
+       if (sign) {
+               if (!g_mime_gpgme_add_signer (ctx, userid, err)) {
+                       g_mime_gpgme_keylist_free (rcpts);
+                       gpgme_data_release (output);
+                       gpgme_data_release (input);
+                       return -1;
+               }
+               
+               error = gpgme_op_encrypt_sign (ctx, rcpts, encrypt_flags, input, output);
+               
+               gpgme_signers_clear (ctx);
+       } else {
+               error = gpgme_op_encrypt (ctx, rcpts, encrypt_flags, input, output);
+       }
+       
+       g_mime_gpgme_keylist_free (rcpts);
+       gpgme_data_release (output);
+       gpgme_data_release (input);
+       
+       if (error != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Encryption failed: %s"), gpgme_strerror 
(error));
+               return -1;
+       }
+       
+       return 0;
+}
+
+static GMimeDecryptResult *
 g_mime_gpgme_get_decrypt_result (gpgme_ctx_t ctx)
 {
        GMimeDecryptResult *result;
@@ -295,8 +499,10 @@ g_mime_gpgme_get_decrypt_result (gpgme_ctx_t ctx)
        if (!(res = gpgme_op_decrypt_result (ctx)) || !res->recipients)
                return result;
        
+#if GPGME_VERSION_NUMBER >= 0x010800
        if (res->session_key)
                result->session_key = g_strdup (res->session_key);
+#endif
        
        recipient = res->recipients;
        while (recipient != NULL) {
@@ -312,4 +518,104 @@ g_mime_gpgme_get_decrypt_result (gpgme_ctx_t ctx)
        return result;
 }
 
+GMimeDecryptResult *
+g_mime_gpgme_decrypt (gpgme_ctx_t ctx, GMimeDecryptFlags flags, const char *session_key,
+                     GMimeStream *istream, GMimeStream *ostream, GError **err)
+{
+       GMimeDecryptResult *result;
+       gpgme_decrypt_result_t res;
+       gpgme_data_t input, output;
+       gpgme_error_t error;
+       
+       if ((error = gpgme_data_new_from_cbs (&input, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
+               return NULL;
+       }
+       
+       if ((error = gpgme_data_new_from_cbs (&output, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
+               gpgme_data_release (input);
+               return NULL;
+       }
+       
+#if GPGME_VERSION_NUMBER >= 0x010800
+       if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
+               gpgme_set_ctx_flag (ctx, "export-session-key", "1");
+       
+       if (session_key)
+               gpgme_set_ctx_flag (ctx, "override-session-key", session_key);
+#endif
+       
+       /* decrypt the input stream */
+       if (gpgme_get_protocol (ctx) == GPGME_PROTOCOL_OpenPGP)
+               error = gpgme_op_decrypt_verify (ctx, input, output);
+       else
+               error = gpgme_op_decrypt (ctx, input, output);
+       
+#if GPGME_VERSION_NUMBER >= 0x010800
+       if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
+               gpgme_set_ctx_flag (ctx, "export-session-key", "0");
+       
+       if (session_key)
+               gpgme_set_ctx_flag (ctx, "override-session-key", NULL);
+#endif
+       
+       gpgme_data_release (output);
+       gpgme_data_release (input);
+       
+       if (error != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Decryption failed: %s"), gpgme_strerror 
(error));
+               return NULL;
+       }
+       
+       return g_mime_gpgme_get_decrypt_result (ctx);
+}
+
+int
+g_mime_gpgme_import (gpgme_ctx_t ctx, GMimeStream *istream, GError **err)
+{
+       gpgme_data_t keydata;
+       gpgme_error_t error;
+       
+       if ((error = gpgme_data_new_from_cbs (&keydata, &gpg_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
+               return -1;
+       }
+       
+       /* import the key(s) */
+       error = gpgme_op_import (ctx, keydata);
+       gpgme_data_release (keydata);
+       
+       if (error != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not import key data: %s"), 
gpgme_strerror (error));
+               return -1;
+       }
+       
+       return 0;
+}
+
+int
+g_mime_gpgme_export (gpgme_ctx_t ctx, const char *keys[], GMimeStream *ostream, GError **err)
+{
+       gpgme_data_t keydata;
+       gpgme_error_t error;
+       guint i;
+       
+       if ((error = gpgme_data_new_from_cbs (&keydata, &gpg_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
+               return -1;
+       }
+       
+       /* export the key(s) */
+       error = gpgme_op_export_ext (ctx, keys, 0, keydata);
+       gpgme_data_release (keydata);
+       
+       if (error != GPG_ERR_NO_ERROR) {
+               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not export key data: %s"), 
gpgme_strerror (error));
+               return -1;
+       }
+       
+       return 0;
+}
+
 #endif /* ENABLE_CRYPTO */
diff --git a/gmime/gmime-gpgme-utils.h b/gmime/gmime-gpgme-utils.h
index 4933be0..601b5a0 100644
--- a/gmime/gmime-gpgme-utils.h
+++ b/gmime/gmime-gpgme-utils.h
@@ -34,16 +34,22 @@ G_GNUC_INTERNAL gpgme_error_t g_mime_gpgme_passphrase_callback (void *hook, cons
                                                                const char *passphrase_info,
                                                                int prev_was_bad, int fd);
 
-G_GNUC_INTERNAL gpgme_key_t g_mime_gpgme_get_key_by_name (gpgme_ctx_t ctx, const char *name,
-                                                         gboolean secret, GError **err);
+G_GNUC_INTERNAL int g_mime_gpgme_sign (gpgme_ctx_t ctx, gpgme_sig_mode_t mode, const char *userid, 
GMimeDigestAlgo digest,
+                                      GMimeStream *istream, GMimeStream *ostream, GError **err);
 
-G_GNUC_INTERNAL gboolean g_mime_gpgme_add_signer (gpgme_ctx_t ctx, const char *signer, GError **err);
+G_GNUC_INTERNAL GMimeSignatureList *g_mime_gpgme_verify (gpgme_ctx_t ctx, GMimeVerifyFlags flags, 
GMimeStream *istream,
+                                                        GMimeStream *sigstream, GMimeStream *ostream, GError 
**err);
 
-G_GNUC_INTERNAL GMimeSignatureList *g_mime_gpgme_get_signatures (gpgme_ctx_t ctx, gboolean verify);
+G_GNUC_INTERNAL int g_mime_gpgme_encrypt (gpgme_ctx_t ctx, gboolean sign, const char *userid, 
GMimeDigestAlgo digest,
+                                         GMimeEncryptFlags flags, GPtrArray *recipients, GMimeStream 
*istream, GMimeStream *ostream,
+                                         GError **err);
 
-G_GNUC_INTERNAL void g_mime_gpgme_keylist_free (gpgme_key_t *keys);
+G_GNUC_INTERNAL GMimeDecryptResult *g_mime_gpgme_decrypt (gpgme_ctx_t ctx, GMimeDecryptFlags flags, const 
char *session_key,
+                                                         GMimeStream *istream, GMimeStream *ostream, GError 
**err);
 
-G_GNUC_INTERNAL GMimeDecryptResult *g_mime_gpgme_get_decrypt_result (gpgme_ctx_t ctx);
+G_GNUC_INTERNAL int g_mime_gpgme_import (gpgme_ctx_t ctx, GMimeStream *istream, GError **err);
+
+G_GNUC_INTERNAL int g_mime_gpgme_export (gpgme_ctx_t ctx, const char *keys[], GMimeStream *ostream, GError 
**err);
 
 G_END_DECLS
 
diff --git a/gmime/gmime-pkcs7-context.c b/gmime/gmime-pkcs7-context.c
index f7fbf1a..ba4a75b 100644
--- a/gmime/gmime-pkcs7-context.c
+++ b/gmime/gmime-pkcs7-context.c
@@ -262,137 +262,6 @@ pkcs7_get_key_exchange_protocol (GMimeCryptoContext *ctx)
        return "application/pkcs7-keys";
 }
 
-#ifdef ENABLE_CRYPTO
-static ssize_t
-pkcs7_stream_read (void *stream, void *buffer, size_t size)
-{
-       return g_mime_stream_read ((GMimeStream *) stream, (char *) buffer, size);
-}
-
-static ssize_t
-pkcs7_stream_write (void *stream, const void *buffer, size_t size)
-{
-       return g_mime_stream_write ((GMimeStream *) stream, (const char *) buffer, size);
-}
-
-static off_t
-pkcs7_stream_seek (void *stream, off_t offset, int whence)
-{
-       switch (whence) {
-       case SEEK_SET:
-               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_SET);
-       case SEEK_CUR:
-               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_CUR);
-       case SEEK_END:
-               return (off_t) g_mime_stream_seek ((GMimeStream *) stream, (gint64) offset, 
GMIME_STREAM_SEEK_END);
-       default:
-               return -1;
-       }
-}
-
-static void
-pkcs7_stream_free (void *stream)
-{
-       /* no-op */
-}
-
-static struct gpgme_data_cbs pkcs7_stream_funcs = {
-       pkcs7_stream_read,
-       pkcs7_stream_write,
-       pkcs7_stream_seek,
-       pkcs7_stream_free
-};
-
-
-
-#define KEY_IS_OK(k)   (!((k)->expired || (k)->revoked ||      \
-                          (k)->disabled || (k)->invalid))
-
-static gpgme_key_t
-pkcs7_get_key_by_name (GMimePkcs7Context *pkcs7, const char *name, gboolean secret, GError **err)
-{
-       time_t now = time (NULL);
-       gpgme_key_t key = NULL;
-       gpgme_subkey_t subkey;
-       gboolean bad = FALSE;
-       gpgme_error_t error;
-       int errval = 0;
-       
-       if ((error = gpgme_op_keylist_start (pkcs7->ctx, name, secret)) != GPG_ERR_NO_ERROR) {
-               if (secret)
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list secret keys for \"%s\": 
%s"), name, gpgme_strerror (error));
-               else
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list keys for \"%s\": %s"), 
name, gpgme_strerror (error));
-               return NULL;
-       }
-       
-       while ((error = gpgme_op_keylist_next (pkcs7->ctx, &key)) == GPG_ERR_NO_ERROR) {
-               /* check if this key and the relevant subkey are usable */
-               if (KEY_IS_OK (key)) {
-                       subkey = key->subkeys;
-                       
-                       while (subkey && ((secret && !subkey->can_sign) ||
-                                         (!secret && !subkey->can_encrypt)))
-                               subkey = subkey->next;
-                       
-                       if (subkey && KEY_IS_OK (subkey) && 
-                           (subkey->expires == 0 || subkey->expires > now))
-                               break;
-                       
-                       if (subkey->expired)
-                               errval = GPG_ERR_KEY_EXPIRED;
-                       else
-                               errval = GPG_ERR_BAD_KEY;
-               } else {
-                       if (key->expired)
-                               errval = GPG_ERR_KEY_EXPIRED;
-                       else
-                               errval = GPG_ERR_BAD_KEY;
-               }
-               
-               gpgme_key_unref (key);
-               bad = TRUE;
-               key = NULL;
-       }
-       
-       gpgme_op_keylist_end (pkcs7->ctx);
-       
-       if (error != GPG_ERR_NO_ERROR && error != GPG_ERR_EOF) {
-               if (secret)
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list secret keys for \"%s\": 
%s"), name, gpgme_strerror (error));
-               else
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list keys for \"%s\": %s"), 
name, gpgme_strerror (error));
-               
-               return NULL;
-       }
-       
-       if (!key) {
-               if (strchr (name, '@')) {
-                       if (bad)
-                               g_set_error (err, GMIME_GPGME_ERROR, errval,
-                                            _("A key for %s is present, but it is expired, disabled, revoked 
or invalid"),
-                                            name);
-                       else
-                               g_set_error (err, GMIME_GPGME_ERROR, GPG_ERR_NOT_FOUND,
-                                            _("Could not find a key for %s"), name);
-               } else {
-                       if (bad)
-                               g_set_error (err, GMIME_GPGME_ERROR, errval,
-                                            _("A key with id %s is present, but it is expired, disabled, 
revoked or invalid"),
-                                            name);
-                       else
-                               g_set_error (err, GMIME_GPGME_ERROR, GPG_ERR_NOT_FOUND,
-                                            _("Could not find a key with id %s"), name);
-               }
-               
-               return NULL;
-       }
-       
-       return key;
-}
-
-#endif /* ENABLE_CRYPTO */
-
 static int
 pkcs7_sign (GMimeCryptoContext *context, gboolean detach, const char *userid, GMimeDigestAlgo digest,
            GMimeStream *istream, GMimeStream *ostream, GError **err)
@@ -400,43 +269,8 @@ pkcs7_sign (GMimeCryptoContext *context, gboolean detach, const char *userid, GM
 #ifdef ENABLE_CRYPTO
        gpgme_sig_mode_t mode = detach ? GPGME_SIG_MODE_DETACH : GPGME_SIG_MODE_NORMAL;
        GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
-       gpgme_sign_result_t result;
-       gpgme_data_t input, output;
-       gpgme_error_t error;
-       
-       if (!g_mime_gpgme_add_signer (pkcs7->ctx, userid, err))
-               return -1;
-       
-       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: %s"), 
gpgme_strerror (error));
-               gpgme_signers_clear (pkcs7->ctx);
-               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: %s"), 
gpgme_strerror (error));
-               gpgme_signers_clear (pkcs7->ctx);
-               gpgme_data_release (input);
-               return -1;
-       }
-       
-       /* sign the input stream */
-       if ((error = gpgme_op_sign (pkcs7->ctx, input, output, mode)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Signing failed: %s"), gpgme_strerror (error));
-               gpgme_signers_clear (pkcs7->ctx);
-               gpgme_data_release (output);
-               gpgme_data_release (input);
-               return -1;
-       }
        
-       gpgme_signers_clear (pkcs7->ctx);
-       gpgme_data_release (output);
-       gpgme_data_release (input);
-       
-       /* return the digest algorithm used for signing */
-       result = gpgme_op_sign_result (pkcs7->ctx);
-       
-       return (GMimeDigestAlgo) result->signatures->hash_algo;
+       return g_mime_gpgme_sign (pkcs7->ctx, mode, userid, digest, istream, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in 
this build"));
        
@@ -450,56 +284,8 @@ pkcs7_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeStream *
 {
 #ifdef ENABLE_CRYPTO
        GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
-       gpgme_data_t sig, signed_text, plain;
-       gpgme_error_t error;
        
-       if (sigstream != NULL) {
-               /* if @sigstream is non-NULL, then it is a detached signature */
-               if ((error = gpgme_data_new_from_cbs (&signed_text, &pkcs7_stream_funcs, istream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-                       return NULL;
-               }
-               
-               if ((error = gpgme_data_new_from_cbs (&sig, &pkcs7_stream_funcs, sigstream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open signature stream: %s"), 
gpgme_strerror (error));
-                       gpgme_data_release (signed_text);
-                       return NULL;
-               }
-               
-               plain = NULL;
-       } else if (ostream != NULL) {
-               /* if @ostream is non-NULL, then we are expected to write the extracted plaintext to it */
-               if ((error = gpgme_data_new_from_cbs (&sig, &pkcs7_stream_funcs, istream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream: %s"), 
gpgme_strerror (error));
-                       return NULL;
-               }
-               
-               if ((error = gpgme_data_new_from_cbs (&plain, &pkcs7_stream_funcs, ostream)) != 
GPG_ERR_NO_ERROR) {
-                       g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream: %s"), 
gpgme_strerror (error));
-                       gpgme_data_release (sig);
-                       return NULL;
-               }
-               
-               signed_text = NULL;
-       } else {
-               g_set_error_literal (err, GMIME_GPGME_ERROR, error, _("Missing signature stream or output 
stream"));
-               return NULL;
-       }
-       
-       error = gpgme_op_verify (pkcs7->ctx, sig, signed_text, plain);
-       if (signed_text)
-               gpgme_data_release (signed_text);
-       if (plain)
-               gpgme_data_release (plain);
-       gpgme_data_release (sig);
-       
-       if (error != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify pkcs7 signature: %s"), 
gpgme_strerror (error));
-               return NULL;
-       }
-       
-       /* get/return the pkcs7 signatures */
-       return g_mime_gpgme_get_signatures (pkcs7->ctx, TRUE);
+       return g_mime_gpgme_verify (pkcs7->ctx, flags, istream, sigstream, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in 
this build"));
        
@@ -507,21 +293,6 @@ pkcs7_verify (GMimeCryptoContext *context, GMimeVerifyFlags flags, GMimeStream *
 #endif /* ENABLE_CRYPTO */
 }
 
-#ifdef ENABLE_CRYPTO
-static void
-key_list_free (gpgme_key_t *keys)
-{
-       gpgme_key_t *key = keys;
-       
-       while (*key != NULL) {
-               gpgme_key_unref (*key);
-               key++;
-       }
-       
-       g_free (keys);
-}
-#endif /* ENABLE_CRYPTO */
-
 static int
 pkcs7_encrypt (GMimeCryptoContext *context, gboolean sign, const char *userid, GMimeDigestAlgo digest,
               GMimeEncryptFlags flags, GPtrArray *recipients, GMimeStream *istream, GMimeStream *ostream,
@@ -529,12 +300,6 @@ pkcs7_encrypt (GMimeCryptoContext *context, gboolean sign, const char *userid, G
 {
 #ifdef ENABLE_CRYPTO
        GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
-       gpgme_encrypt_flags_t encrypt_flags = 0;
-       gpgme_data_t input, output;
-       gpgme_error_t error;
-       gpgme_key_t *rcpts;
-       gpgme_key_t key;
-       guint i;
        
        if (sign) {
                g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED,
@@ -542,45 +307,7 @@ pkcs7_encrypt (GMimeCryptoContext *context, gboolean sign, const char *userid, G
                return -1;
        }
        
-       if (flags & GMIME_ENCRYPT_FLAGS_ALWAYS_TRUST)
-               encrypt_flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
-       
-       /* 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))) {
-                       g_mime_gpgme_keylist_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: %s"), 
gpgme_strerror (error));
-               g_mime_gpgme_keylist_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: %s"), 
gpgme_strerror (error));
-               g_mime_gpgme_keylist_free (rcpts);
-               gpgme_data_release (input);
-               return -1;
-       }
-       
-       /* encrypt the input stream */
-       error = gpgme_op_encrypt (pkcs7->ctx, rcpts, encrypt_flags, input, output);
-       g_mime_gpgme_keylist_free (rcpts);
-       gpgme_data_release (output);
-       gpgme_data_release (input);
-       
-       if (error != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Encryption failed: %s"), gpgme_strerror 
(error));
-               return -1;
-       }
-       
-       return 0;
+       return g_mime_gpgme_encrypt (pkcs7->ctx, sign, userid, digest, flags, recipients, istream, ostream, 
err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in 
this build"));
        
@@ -594,53 +321,8 @@ pkcs7_decrypt (GMimeCryptoContext *context, GMimeDecryptFlags flags, const char
 {
 #ifdef ENABLE_CRYPTO
        GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
-       GMimeDecryptResult *result;
-       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: %s"), 
gpgme_strerror (error));
-               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: %s"), 
gpgme_strerror (error));
-               gpgme_data_release (input);
-               return NULL;
-       }
-       
-       if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
-               gpgme_set_ctx_flag (pkcs7->ctx, "export-session-key", "1");
-       
-       if (session_key)
-               gpgme_set_ctx_flag (pkcs7->ctx, "override-session-key", session_key);
-       
-       /* decrypt the input stream */
-       if ((error = gpgme_op_decrypt (pkcs7->ctx, input, output)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Decryption failed: %s"), gpgme_strerror 
(error));
-               
-               if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
-                       gpgme_set_ctx_flag (pkcs7->ctx, "export-session-key", "0");
-               
-               if (session_key)
-                       gpgme_set_ctx_flag (pkcs7->ctx, "override-session-key", NULL);
-               
-               gpgme_data_release (output);
-               gpgme_data_release (input);
-               return NULL;
-       }
-       
-       if (flags & GMIME_DECRYPT_FLAGS_EXPORT_SESSION_KEY)
-               gpgme_set_ctx_flag (pkcs7->ctx, "export-session-key", "0");
-       
-       if (session_key)
-               gpgme_set_ctx_flag (pkcs7->ctx, "override-session-key", NULL);
        
-       gpgme_data_release (output);
-       gpgme_data_release (input);
-       
-       return g_mime_gpgme_get_decrypt_result (pkcs7->ctx);
+       return g_mime_gpgme_decrypt (pkcs7->ctx, flags, session_key, istream, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in 
this build"));
        
@@ -653,24 +335,8 @@ pkcs7_import_keys (GMimeCryptoContext *context, GMimeStream *istream, GError **e
 {
 #ifdef ENABLE_CRYPTO
        GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
-       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: %s"), 
gpgme_strerror (error));
-               return -1;
-       }
-       
-       /* import the key(s) */
-       if ((error = gpgme_op_import (pkcs7->ctx, keydata)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not import key data: %s"), 
gpgme_strerror (error));
-               gpgme_data_release (keydata);
-               return -1;
-       }
-       
-       gpgme_data_release (keydata);
        
-       return 0;
+       return g_mime_gpgme_import (pkcs7->ctx, istream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in 
this build"));
        
@@ -683,25 +349,8 @@ pkcs7_export_keys (GMimeCryptoContext *context, const char *keys[], GMimeStream
 {
 #ifdef ENABLE_CRYPTO
        GMimePkcs7Context *pkcs7 = (GMimePkcs7Context *) context;
-       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: %s"), 
gpgme_strerror (error));
-               return -1;
-       }
-       
-       /* export the key(s) */
-       if ((error = gpgme_op_export_ext (pkcs7->ctx, keys, 0, keydata)) != GPG_ERR_NO_ERROR) {
-               g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not export key data: %s"), 
gpgme_strerror (error));
-               gpgme_data_release (keydata);
-               return -1;
-       }
-       
-       gpgme_data_release (keydata);
        
-       return 0;
+       return g_mime_gpgme_export (pkcs7->ctx, keys, ostream, err);
 #else
        g_set_error_literal (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in 
this build"));
        
diff --git a/tests/test-pgpmime.c b/tests/test-pgpmime.c
index 31c4247..1c5f247 100644
--- a/tests/test-pgpmime.c
+++ b/tests/test-pgpmime.c
@@ -354,15 +354,17 @@ test_multipart_encrypted (GMimeCryptoContext *ctx, gboolean sign,
                throw (ex);
        }
        
+#if GPGME_VERSION_NUMBER >= 0x010800
        if (!result->session_key) {
                ex = exception_new ("No session key returned!");
                throw (ex);
        }
        ret = g_strdup (result->session_key);
+#endif
        
        if (result->signatures)
                v(print_verify_results (result->signatures));
-
+       
        if (sign) {
                status = get_sig_status (result->signatures);
                
@@ -377,7 +379,7 @@ test_multipart_encrypted (GMimeCryptoContext *ctx, gboolean sign,
        
        if (ex != NULL) {
                g_free (ret);
-               ret = 0;
+               ret = NULL;
                throw (ex);
        }
        
@@ -394,9 +396,10 @@ test_multipart_encrypted (GMimeCryptoContext *ctx, gboolean sign,
        
        if (ex != NULL) {
                g_free (ret);
-               ret = 0;
+               ret = NULL;
                throw (ex);
        }
+       
        return ret;
 }
 
@@ -493,11 +496,15 @@ int main (int argc, char *argv[])
        } catch (ex) {
                testsuite_check_failed ("multipart/encrypted failed: %s", ex->message);
        } finally;
+       
        if (cleartext)
                g_object_unref (cleartext);
+       
        if (stream)
                g_object_unref (stream);
+       
        cleartext = stream = NULL;
+       
        if (session_key) {
                memset (session_key, 0, strlen (session_key));
                g_free (session_key);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]