From 748aa18dc6ca9cb25e534fcf2028fb61fde98318 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Wed, 6 Mar 2002 01:40:25 +0000 Subject: [PATCH] doc/ 2002-03-06 Marcus Brinkmann * gpgme.texi (Encrypting a Plaintext): Document symmetric encryption. gpgme/ 2002-03-06 Marcus Brinkmann * encrypt.c (_gpgme_encrypt_sym_status_handler): New function. (gpgme_op_encrypt_start): New variable SYMMETRIC, set it if RECP is null, and if it is set, use _gpgme_encrypt_sym_status_handler as status handler and run _gpgme_passphrase_start. * rungpg.c (_gpgme_gpg_op_encrypt): If RECP is zero, do symmetric encryption. * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): If RECP is zero, return error value. * rungpg.c (_gpgme_gpg_op_verify): Add "--" argument. tests/ 2002-03-06 Marcus Brinkmann * gpg/t-encrypt-sym.c: New file. * gpg/Makefile.am (TESTS): Add t-encrypt-sym. --- NEWS | 9 +++ doc/ChangeLog | 5 ++ doc/gpgme.texi | 7 ++ gpgme/ChangeLog | 13 ++++ gpgme/encrypt.c | 25 ++++++- gpgme/engine-gpgsm.c | 2 + gpgme/rungpg.c | 21 ++++-- tests/ChangeLog | 5 ++ tests/gpg/Makefile.am | 5 +- tests/gpg/t-encrypt-sym.c | 135 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 215 insertions(+), 12 deletions(-) create mode 100644 tests/gpg/t-encrypt-sym.c diff --git a/NEWS b/NEWS index 3e70ac41..2f919448 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ + * gpgme_op_encrypt can be called with RECIPIENTS being 0. In this + case, symmetric encryption is performed. Note that this requires a + passphrase from the user. + + * Interface changes relative to the 0.3.4 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_op_encrypt EXTENDED: Symmetric encryption possible +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Noteworthy changes in version 0.3.4 (2002-03-04) ------------------------------------------------ diff --git a/doc/ChangeLog b/doc/ChangeLog index bdd5f292..72b31b8f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2002-03-06 Marcus Brinkmann + + * gpgme.texi (Encrypting a Plaintext): Document symmetric + encryption. + 2002-03-06 Marcus Brinkmann * gpgme.texi (Error Strings): Add example. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 0c2d4136..855f0d49 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -2289,6 +2289,13 @@ encrypted for all valid recipients and returned in @var{cipher}. More information about the invalid recipients is available with @code{gpgme_get_op_info}. @xref{Detailed Results}. +If @var{recp} is @code{NULL}, symmetric rather than public key +encryption is performed. Symmetrically encrypted cipher text can be +deciphered with @code{gpgme_op_decrypt}. Note that in this case the +crypto backend needs to retrieve a passphrase from the user. +Symmetric encryption is currently only supported for the OpenPGP +crypto backend. + The function returns @code{GPGME_No_Error} if the ciphertext could be created successfully, @code{GPGME_Invalid_Value} if @var{ctx}, @var{rset}, @var{plain} or @var{cipher} is not a valid pointer, diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index f2104c74..f5272153 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,16 @@ +2002-03-06 Marcus Brinkmann + + * encrypt.c (_gpgme_encrypt_sym_status_handler): New function. + (gpgme_op_encrypt_start): New variable SYMMETRIC, set it if RECP + is null, and if it is set, use _gpgme_encrypt_sym_status_handler + as status handler and run _gpgme_passphrase_start. + * rungpg.c (_gpgme_gpg_op_encrypt): If RECP is zero, do symmetric + encryption. + * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): If RECP is zero, + return error value. + + * rungpg.c (_gpgme_gpg_op_verify): Add "--" argument. + 2002-03-03 Marcus Brinkmann * passphrase.c (_gpgme_passphrase_status_handler): Also set the diff --git a/gpgme/encrypt.c b/gpgme/encrypt.c index ffaf2d90..0a3970c1 100644 --- a/gpgme/encrypt.c +++ b/gpgme/encrypt.c @@ -135,11 +135,19 @@ _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) } +void +_gpgme_encrypt_sym_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) +{ + _gpgme_passphrase_status_handler (ctx, code, args); +} + + GpgmeError gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain, GpgmeData ciph) { int err = 0; + int symmetric = 0; fail_on_pending_request (ctx); ctx->pending = 1; @@ -147,9 +155,10 @@ gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain, _gpgme_release_result (ctx); /* Do some checks. */ - if (!gpgme_recipients_count (recp)) + if (!recp) + symmetric = 1; + else if (!gpgme_recipients_count (recp)) { - /* Fixme: In this case we should do symmentric encryption. */ err = mk_error (No_Recipients); goto leave; } @@ -162,7 +171,17 @@ gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain, if (err) goto leave; - _gpgme_engine_set_status_handler (ctx->engine, _gpgme_encrypt_status_handler, + if (symmetric) + { + err = _gpgme_passphrase_start (ctx); + if (err) + goto leave; + } + + _gpgme_engine_set_status_handler (ctx->engine, + symmetric + ? _gpgme_encrypt_sym_status_handler + : _gpgme_encrypt_status_handler, ctx); _gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity); diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index c2d28b54..d78a5200 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -484,6 +484,8 @@ _gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp, if (!gpgsm) return mk_error (Invalid_Value); + if (!recp) + return mk_error (Not_Implemented); gpgsm->command = xtrystrdup ("ENCRYPT"); if (!gpgsm->command) diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index be639b97..797ae43f 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -1308,18 +1308,23 @@ _gpgme_gpg_op_encrypt (GpgObject gpg, GpgmeRecipients recp, GpgmeData plain, GpgmeData ciph, int use_armor) { GpgmeError err; + int symmetric = !recp; + + err = _gpgme_gpg_add_arg (gpg, symmetric ? "--symmetric" : "--encrypt"); - err = _gpgme_gpg_add_arg (gpg, "--encrypt"); if (!err && use_armor) err = _gpgme_gpg_add_arg (gpg, "--armor"); - /* If we know that all recipients are valid (full or ultimate trust) - * we can suppress further checks */ - if (!err && _gpgme_recipients_all_valid (recp)) - err = _gpgme_gpg_add_arg (gpg, "--always-trust"); + if (!symmetric) + { + /* If we know that all recipients are valid (full or ultimate trust) + we can suppress further checks. */ + if (!err && !symmetric && _gpgme_recipients_all_valid (recp)) + err = _gpgme_gpg_add_arg (gpg, "--always-trust"); - if (!err) - err = _gpgme_append_gpg_args_from_recipients (gpg, recp); + if (!err) + err = _gpgme_append_gpg_args_from_recipients (gpg, recp); + } /* Tell the gpg object about the data. */ if (!err) @@ -1560,6 +1565,8 @@ _gpgme_gpg_op_verify (GpgObject gpg, GpgmeData sig, GpgmeData text) err = _gpgme_gpg_add_arg (gpg, "--output"); if (!err) err = _gpgme_gpg_add_arg (gpg, "-"); + if (!err) + err = _gpgme_gpg_add_arg (gpg, "--"); if (!err) err = _gpgme_gpg_add_data (gpg, sig, 0); if (!err) diff --git a/tests/ChangeLog b/tests/ChangeLog index 83544c74..6cee9803 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2002-03-06 Marcus Brinkmann + + * gpg/t-encrypt-sym.c: New file. + * gpg/Makefile.am (TESTS): Add t-encrypt-sym. + 2002-03-05 Marcus Brinkmann * gpg/Makefile.am (CLEANFILES): Remove random_seed, which is now diff --git a/tests/gpg/Makefile.am b/tests/gpg/Makefile.am index 6de6ce0e..7518716e 100644 --- a/tests/gpg/Makefile.am +++ b/tests/gpg/Makefile.am @@ -23,8 +23,9 @@ GPG = @GPG@ TESTS_ENVIRONMENT = GNUPGHOME=. -TESTS = t-encrypt t-encrypt-sign t-sign t-signers t-decrypt t-verify \ - t-decrypt-verify t-keylist t-export t-import t-trustlist +TESTS = t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \ + t-decrypt t-verify t-decrypt-verify t-keylist t-export \ + t-import t-trustlist CLEANFILES = secring.gpg pubring.gpg trustdb.gpg DISTCLEANFILES = pubring.gpg~ random_seed diff --git a/tests/gpg/t-encrypt-sym.c b/tests/gpg/t-encrypt-sym.c new file mode 100644 index 00000000..72672d3e --- /dev/null +++ b/tests/gpg/t-encrypt-sym.c @@ -0,0 +1,135 @@ +/* t-encrypt.c - regression test + * Copyright (C) 2000 Werner Koch (dd9jn) + * Copyright (C) 2001 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include + +#include + +#define fail_if_err(a) do { if(a) { \ + fprintf (stderr, "%s:%d: GpgmeError %s\n", \ + __FILE__, __LINE__, gpgme_strerror(a)); \ + exit (1); } \ + } while(0) + +static void +print_data (GpgmeData dh) +{ + char buf[100]; + size_t nread; + GpgmeError err; + + err = gpgme_data_rewind (dh); + fail_if_err (err); + while (!(err = gpgme_data_read (dh, buf, 100, &nread))) + fwrite ( buf, nread, 1, stdout ); + if (err != GPGME_EOF) + fail_if_err (err); +} + + +static const char * +passphrase_cb ( void *opaque, const char *desc, void **r_hd ) +{ + const char *pass; + + if ( !desc ) { + /* cleanup by looking at *r_hd */ + + + return NULL; + } + + pass = "abc"; + fprintf (stderr, "%% requesting passphrase for `%s': ", desc ); + fprintf (stderr, "sending `%s'\n", pass ); + + return pass; +} + + +int +main (int argc, char **argv) +{ + GpgmeCtx ctx; + GpgmeError err; + GpgmeData plain, cipher; + const char *text = "Hallo Leute\n"; + char *text2; + int i; + + err = gpgme_check_engine (); + fail_if_err (err); + + do + { + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 1); + if (!getenv("GPG_AGENT_INFO")) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + err = gpgme_data_new_from_mem (&plain, text, strlen (text), 0); + fail_if_err (err); + + err = gpgme_data_new (&cipher); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, 0, plain, cipher); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result Encryption:\n", stdout); + print_data (cipher); + fputs ("End Result.\n", stdout); + + err = gpgme_data_rewind (cipher); + fail_if_err (err); + + gpgme_data_release (plain); + err = gpgme_data_new (&plain); + fail_if_err (err); + + err = gpgme_op_decrypt (ctx, cipher, plain); + fail_if_err (err); + + fputs ("Begin Result Decryption:\n", stdout); + print_data (plain); + fputs ("End Result.\n", stdout); + + text2 = gpgme_data_release_and_get_mem (plain, &i); + if (strncmp (text, text2, i)) + { + fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__); + exit (1); + } + + gpgme_data_release (cipher); + gpgme_release (ctx); + } + while (argc > 1 && !strcmp (argv[1], "--loop")); + + return 0; +} + +