aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--doc/gpgme.texi17
-rw-r--r--src/engine-gpg.c46
-rw-r--r--src/engine-gpgsm.c4
-rw-r--r--src/engine-uiserver.c4
-rw-r--r--src/gpgme.h.in3
-rw-r--r--src/sign.c3
-rw-r--r--tests/run-sign.c23
8 files changed, 82 insertions, 23 deletions
diff --git a/NEWS b/NEWS
index 81bd564a..e9e2ed28 100644
--- a/NEWS
+++ b/NEWS
@@ -1,12 +1,13 @@
Noteworthy changes in version 1.23.3 (unrelease)
-------------------------------------------------
- * Extended gpgme_op_encrypt* and gpgme_op_encrypt_sign* to allow reading
- the input data directly from a file. [T6550]
+ * Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
+ to allow reading the input data directly from a file. [T6550]
* Interface changes relative to the 1.23.2 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_ENCRYPT_FILE NEW.
+ GPGME_SIG_MODE_FILE NEW.
Noteworthy changes in version 1.23.2 (2023-11-28)
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index 0ec70a55..e7a568a3 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -6366,6 +6366,16 @@ A signed archive is created from the given files and directories. This
feature is currently only supported for the OpenPGP crypto engine and requires
GnuPG 2.4.1.
+@item GPGME_SIG_MODE_FILE
+@since{1.24.0}
+
+The filename set with @code{gpgme_data_set_file_name} for the data object
+@var{plain} is passed to gpg, so that gpg reads the plaintext directly from
+this file instead of from the data object @var{plain}. This flag can be
+combined with @code{GPGME_SIG_MODE_NORMAL}, @code{GPGME_SIG_MODE_DETACH},
+and @code{GPGME_SIG_MODE_CLEAR}, but not with @code{GPGME_SIG_MODE_ARCHIVE}.
+This feature is currently only supported for the OpenPGP crypto engine.
+
@end table
@end deftp
@@ -6379,7 +6389,12 @@ if that is not set, by the encoding specified for @var{sig}), the text
mode attributes set for the context @var{ctx} and the requested signature
mode @var{mode}.
-If signature mode @code{GPGME_SIG_MODE_ARCHIVE} is requested, then a
+If the signature mode flag @code{GPGME_SIG_MODE_FILE} is set and a filename
+has been set with @code{gpgme_data_set_file_name} for the data object
+@var{plain}, then this filename is passed to gpg, so that gpg reads the
+plaintext directly from this file instead of from the data object @var{plain}.
+
+If signature mode @code{GPGME_SIG_MODE_ARCHIVE} is requested then a
signed archive is created from the files and directories given as
NUL-separated list in the data object @var{plain}. The paths of the files
and directories have to be given as paths relative to the current working
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 123760be..cc249e7b 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -3615,25 +3615,32 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
{
engine_gpg_t gpg = engine;
gpgme_error_t err;
- const char *output = NULL;
+ const char *file_name = NULL;
+ unsigned int mode = flags & (GPGME_SIG_MODE_NORMAL
+ |GPGME_SIG_MODE_DETACH
+ |GPGME_SIG_MODE_CLEAR
+ |GPGME_SIG_MODE_ARCHIVE);
(void)include_certs;
- if ((flags != GPGME_SIG_MODE_NORMAL) && (flags != GPGME_SIG_MODE_DETACH)
- && (flags != GPGME_SIG_MODE_CLEAR) && (flags != GPGME_SIG_MODE_ARCHIVE))
+ if ((mode != GPGME_SIG_MODE_NORMAL) && (mode != GPGME_SIG_MODE_DETACH)
+ && (mode != GPGME_SIG_MODE_CLEAR) && (mode != GPGME_SIG_MODE_ARCHIVE))
return gpg_error (GPG_ERR_INV_VALUE);
- gpg->flags.use_gpgtar = !!(flags & GPGME_SIG_MODE_ARCHIVE);
+ gpg->flags.use_gpgtar = !!(mode == GPGME_SIG_MODE_ARCHIVE);
if (gpg->flags.use_gpgtar && !have_usable_gpgtar (gpg))
return gpg_error (GPG_ERR_NOT_SUPPORTED);
- if (flags & GPGME_SIG_MODE_CLEAR)
+ if (gpg->flags.use_gpgtar && (flags & GPGME_SIG_MODE_FILE))
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (mode == GPGME_SIG_MODE_CLEAR)
err = add_arg (gpg, "--clearsign");
else
{
err = add_arg (gpg, "--sign");
- if (!err && (flags & GPGME_SIG_MODE_DETACH))
+ if (!err && (mode == GPGME_SIG_MODE_DETACH))
err = add_arg (gpg, "--detach");
if (!err && use_armor)
err = add_gpg_arg (gpg, "--armor");
@@ -3657,20 +3664,24 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
err = append_args_from_sig_notations (gpg, ctx, NOTATION_FLAG_SIG);
if (!err)
+ err = add_arg (gpg, "--output");
+ if (!err)
{
- output = gpgme_data_get_file_name (out);
+ const char *output = gpgme_data_get_file_name (out);
if (output)
+ err = add_arg (gpg, output);
+ else
{
- err = add_arg (gpg, "--output");
+ err = add_arg (gpg, "-");
if (!err)
- err = add_arg (gpg, output);
+ err = add_data (gpg, out, 1, 1);
}
}
-
+ if (!err)
+ file_name = gpgme_data_get_file_name (in);
/* Tell the gpg object about the data. */
if (gpg->flags.use_gpgtar)
{
- const char *file_name = gpgme_data_get_file_name (in);
if (!err && file_name)
{
err = add_arg (gpg, "--directory");
@@ -3689,9 +3700,17 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
if (!err)
err = add_data (gpg, in, 0, 0);
}
+ else if (flags & GPGME_SIG_MODE_FILE)
+ {
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err && (!file_name || !*file_name))
+ err = gpg_error (GPG_ERR_INV_VALUE);
+ if (!err)
+ err = add_arg (gpg, file_name);
+ }
else
{
- const char *file_name = gpgme_data_get_file_name (in);
if (!err && file_name)
err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0);
if (!err)
@@ -3702,9 +3721,6 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
err = add_data (gpg, in, -1, 0);
}
- if (!err && !output)
- err = add_data (gpg, out, 1, 1);
-
if (!err)
err = start (gpg);
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index 014507d4..fa89ae3f 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -2128,7 +2128,9 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
- if (flags & (GPGME_SIG_MODE_CLEAR | GPGME_SIG_MODE_ARCHIVE))
+ if (flags & (GPGME_SIG_MODE_CLEAR
+ | GPGME_SIG_MODE_ARCHIVE
+ | GPGME_SIG_MODE_FILE))
return gpg_error (GPG_ERR_INV_VALUE);
/* FIXME: This does not work as RESET does not reset it so we can't
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index a116feb9..3e9836af 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -1237,7 +1237,9 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
- if (flags & (GPGME_SIG_MODE_CLEAR | GPGME_SIG_MODE_ARCHIVE))
+ if (flags & (GPGME_SIG_MODE_CLEAR
+ | GPGME_SIG_MODE_ARCHIVE
+ | GPGME_SIG_MODE_FILE))
return gpg_error (GPG_ERR_INV_VALUE);
if (gpgrt_asprintf (&cmd, "SIGN%s%s", protocol,
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index ccc7b026..c8eba0a5 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -309,7 +309,8 @@ typedef enum
GPGME_SIG_MODE_NORMAL = 0,
GPGME_SIG_MODE_DETACH = 1,
GPGME_SIG_MODE_CLEAR = 2,
- GPGME_SIG_MODE_ARCHIVE = 4
+ GPGME_SIG_MODE_ARCHIVE = 4,
+ GPGME_SIG_MODE_FILE = 8
}
gpgme_sig_mode_t;
diff --git a/src/sign.c b/src/sign.c
index 1563c1dd..56b2d5fb 100644
--- a/src/sign.c
+++ b/src/sign.c
@@ -450,7 +450,8 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
if (flags & ~(GPGME_SIG_MODE_DETACH
|GPGME_SIG_MODE_CLEAR
- |GPGME_SIG_MODE_ARCHIVE))
+ |GPGME_SIG_MODE_ARCHIVE
+ |GPGME_SIG_MODE_FILE))
return gpg_error (GPG_ERR_INV_VALUE);
if (!plain)
diff --git a/tests/run-sign.c b/tests/run-sign.c
index 07482dd5..c04fa819 100644
--- a/tests/run-sign.c
+++ b/tests/run-sign.c
@@ -87,6 +87,8 @@ show_usage (int ex)
" --sender MBOX use MBOX as sender address\n"
" --include-key-block use this option with gpg\n"
" --clear create a clear text signature\n"
+ " --detach create a detached signature\n"
+ " --direct-file-io pass FILE instead of stream with content of FILE to backend\n"
" --archive create a signed archive with the given file or directory\n"
" --directory DIR switch to directory DIR before creating the archive\n"
" --output FILE write output to FILE instead of stdout\n"
@@ -113,6 +115,7 @@ main (int argc, char **argv)
int use_loopback = 0;
int include_key_block = 0;
int diagnostics = 0;
+ int direct_file_io = 0;
const char *sender = NULL;
const char *s;
@@ -185,6 +188,16 @@ main (int argc, char **argv)
sigmode = GPGME_SIG_MODE_CLEAR;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--detach"))
+ {
+ sigmode = GPGME_SIG_MODE_DETACH;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--direct-file-io"))
+ {
+ direct_file_io = 1;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--archive"))
{
sigmode = GPGME_SIG_MODE_ARCHIVE;
@@ -269,7 +282,15 @@ main (int argc, char **argv)
}
}
- if (sigmode == GPGME_SIG_MODE_ARCHIVE)
+ if (direct_file_io)
+ {
+ sigmode |= GPGME_SIG_MODE_FILE;
+ err = gpgme_data_new (&in);
+ fail_if_err (err);
+ err = gpgme_data_set_file_name (in, *argv);
+ fail_if_err (err);
+ }
+ else if (sigmode == GPGME_SIG_MODE_ARCHIVE)
{
const char *path = *argv;
err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);