summaryrefslogtreecommitdiff
path: root/g10
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2023-02-01 18:02:19 +0900
committerJinWang An <jinwang.an@samsung.com>2023-02-01 18:02:19 +0900
commit0d6c0bc071b2e571c18781271972f6f9ee62dc8a (patch)
treec5e1a47f591d580b340ebc524b0061ebc1f56f29 /g10
parent7909696cfccd5cb051854ae81d49750d09b23ff7 (diff)
downloadgpg2-upstream.tar.gz
gpg2-upstream.tar.bz2
gpg2-upstream.zip
Imported Upstream version 2.4.0upstream/2.4.0upstream
Diffstat (limited to 'g10')
-rw-r--r--g10/Makefile.am22
-rw-r--r--g10/Makefile.in60
-rw-r--r--g10/all-tests.scm7
-rw-r--r--g10/armor.c30
-rw-r--r--g10/build-packet.c24
-rw-r--r--g10/call-agent.c20
-rw-r--r--g10/call-agent.h2
-rw-r--r--g10/call-keyboxd.c2
-rw-r--r--g10/card-util.c1
-rw-r--r--g10/cipher-aead.c4
-rw-r--r--g10/decrypt-data.c14
-rw-r--r--g10/ecdh.c23
-rw-r--r--g10/encrypt.c17
-rw-r--r--g10/exec.c115
-rw-r--r--g10/exec.h1
-rw-r--r--g10/export.c446
-rw-r--r--g10/gpg.c148
-rw-r--r--g10/gpgv.c8
-rw-r--r--g10/import.c135
-rw-r--r--g10/kbnode.c13
-rw-r--r--g10/keydb.h1
-rw-r--r--g10/keyedit.c208
-rw-r--r--g10/keyedit.h1
-rw-r--r--g10/keygen.c57
-rw-r--r--g10/keylist.c254
-rw-r--r--g10/main.h11
-rw-r--r--g10/mainproc.c2
-rw-r--r--g10/misc.c11
-rw-r--r--g10/options.h14
-rw-r--r--g10/parse-packet.c48
-rw-r--r--g10/photoid.c109
-rw-r--r--g10/pkclist.c4
-rw-r--r--g10/test-stubs.c8
-rw-r--r--g10/trustdb.c50
34 files changed, 1202 insertions, 668 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am
index eb23573..80b5b89 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -47,9 +47,7 @@ endif
# NB: We use noinst_ for gpg and gpgv so that we can install them with
# the install-hook target under the name gpg2/gpgv2.
noinst_PROGRAMS = gpg
-if !HAVE_W32CE_SYSTEM
noinst_PROGRAMS += gpgv
-endif
noinst_PROGRAMS += $(module_tests)
if DISABLE_TESTS
TESTS =
@@ -170,15 +168,15 @@ gpgv_SOURCES = gpgv.c \
verify.c
LDADD = $(needed_libs) ../common/libgpgrl.a \
- $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS)
+ $(ZLIBS) $(LIBINTL) $(CAPLIBS)
gpg_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
- $(LIBICONV) $(resource_objs) $(extra_sys_libs)
-gpg_LDFLAGS = $(extra_bin_ldflags)
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
+ $(LIBICONV) $(resource_objs)
+gpg_LDFLAGS =
gpgv_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
- $(LIBICONV) $(resource_objs) $(extra_sys_libs)
-gpgv_LDFLAGS = $(extra_bin_ldflags)
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
+ $(LIBICONV) $(resource_objs)
+gpgv_LDFLAGS =
t_common_ldadd =
@@ -187,17 +185,17 @@ t_rmd160_SOURCES = t-rmd160.c rmd160.c
t_rmd160_LDADD = $(t_common_ldadd)
t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source)
t_keydb_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
t_keydb_get_keyblock_SOURCES = t-keydb-get-keyblock.c test-stubs.c \
$(common_source)
t_keydb_get_keyblock_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
t_stutter_SOURCES = t-stutter.c test-stubs.c \
$(common_source)
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
diff --git a/g10/Makefile.in b/g10/Makefile.in
index 8574cff..77ae8a8 100644
--- a/g10/Makefile.in
+++ b/g10/Makefile.in
@@ -142,10 +142,9 @@ host_triplet = @host@
@GNUPG_DIRMNGR_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_8 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
-noinst_PROGRAMS = gpg$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
-@HAVE_W32CE_SYSTEM_FALSE@am__append_9 = gpgv
-@DISABLE_TESTS_FALSE@TESTS = $(am__EXEEXT_2)
-@HAVE_W32_SYSTEM_TRUE@am__append_10 = gpg-w32info.o
+noinst_PROGRAMS = gpg$(EXEEXT) gpgv$(EXEEXT) $(am__EXEEXT_1)
+@DISABLE_TESTS_FALSE@TESTS = $(am__EXEEXT_1)
+@HAVE_W32_SYSTEM_TRUE@am__append_9 = gpg-w32info.o
subdir = g10
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
@@ -167,8 +166,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = gpg.w32-manifest
CONFIG_CLEAN_VPATH_FILES =
-@HAVE_W32CE_SYSTEM_FALSE@am__EXEEXT_1 = gpgv$(EXEEXT)
-am__EXEEXT_2 = t-rmd160$(EXEEXT) t-keydb$(EXEEXT) \
+am__EXEEXT_1 = t-rmd160$(EXEEXT) t-keydb$(EXEEXT) \
t-keydb-get-keyblock$(EXEEXT) t-stutter$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
am__gpg_SOURCES_DIST = gpg.c keyedit.c keyedit.h server.c gpg.h dek.h \
@@ -217,13 +215,12 @@ am_gpg_OBJECTS = gpg.$(OBJEXT) keyedit.$(OBJEXT) $(am__objects_6)
gpg_OBJECTS = $(am_gpg_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = $(needed_libs) ../common/libgpgrl.a \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
gpg_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(resource_objs) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(resource_objs)
gpg_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(gpg_LDFLAGS) $(LDFLAGS) -o \
$@
am__gpgv_SOURCES_DIST = gpgv.c gpg.h dek.h build-packet.c compress.c \
@@ -238,8 +235,8 @@ am_gpgv_OBJECTS = gpgv.$(OBJEXT) $(am__objects_2) verify.$(OBJEXT)
gpgv_OBJECTS = $(am_gpgv_OBJECTS)
gpgv_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(resource_objs) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(resource_objs)
gpgv_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(gpgv_LDFLAGS) $(LDFLAGS) \
-o $@
am__t_keydb_SOURCES_DIST = t-keydb.c test-stubs.c gpg.h dek.h \
@@ -256,7 +253,7 @@ t_keydb_OBJECTS = $(am_t_keydb_OBJECTS)
t_keydb_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am__t_keydb_get_keyblock_SOURCES_DIST = t-keydb-get-keyblock.c \
test-stubs.c gpg.h dek.h build-packet.c compress.c \
compress-bz2.c filter.h free-packet.c getkey.c expand-group.c \
@@ -272,7 +269,8 @@ t_keydb_get_keyblock_OBJECTS = $(am_t_keydb_get_keyblock_OBJECTS)
t_keydb_get_keyblock_DEPENDENCIES = $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
am_t_rmd160_OBJECTS = t-rmd160.$(OBJEXT) rmd160.$(OBJEXT)
t_rmd160_OBJECTS = $(am_t_rmd160_OBJECTS)
t_rmd160_DEPENDENCIES = $(am__DEPENDENCIES_1)
@@ -290,7 +288,7 @@ t_stutter_OBJECTS = $(am_t_stutter_OBJECTS)
t_stutter_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -615,17 +613,7 @@ AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(am__append_1) \
$(am__append_2) $(am__append_3) $(am__append_4) \
$(am__append_5) $(am__append_6) $(am__append_7) \
$(am__append_8)
-@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
-
-# Under Windows we use LockFileEx. WindowsCE provides this only on
-# the WindowsMobile 6 platform and thus we need to use the coredll6
-# import library. We also want to use a stacksize of 256k instead of
-# the 2MB which is the default with cegcc. 256k is the largest stack
-# we use with pth.
-@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
-@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
-@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
-resource_objs = $(am__append_10)
+resource_objs = $(am__append_9)
# Convenience macros
libcommon = ../common/libcommon.a
@@ -734,39 +722,39 @@ gpgv_SOURCES = gpgv.c \
verify.c
LDADD = $(needed_libs) ../common/libgpgrl.a \
- $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS)
+ $(ZLIBS) $(LIBINTL) $(CAPLIBS)
gpg_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
- $(LIBICONV) $(resource_objs) $(extra_sys_libs)
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
+ $(LIBICONV) $(resource_objs)
-gpg_LDFLAGS = $(extra_bin_ldflags)
+gpg_LDFLAGS =
gpgv_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
- $(LIBICONV) $(resource_objs) $(extra_sys_libs)
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
+ $(LIBICONV) $(resource_objs)
-gpgv_LDFLAGS = $(extra_bin_ldflags)
+gpgv_LDFLAGS =
t_common_ldadd =
module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter
t_rmd160_SOURCES = t-rmd160.c rmd160.c
t_rmd160_LDADD = $(t_common_ldadd)
t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source)
t_keydb_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
t_keydb_get_keyblock_SOURCES = t-keydb-get-keyblock.c test-stubs.c \
$(common_source)
t_keydb_get_keyblock_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
t_stutter_SOURCES = t-stutter.c test-stubs.c \
$(common_source)
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
- $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
all: all-am
diff --git a/g10/all-tests.scm b/g10/all-tests.scm
index 982220b..02fcde7 100644
--- a/g10/all-tests.scm
+++ b/g10/all-tests.scm
@@ -27,9 +27,10 @@
(parse-makefile-expand filename expander key))
(map (lambda (name)
- (test::binary #f
- (path-join "g10" name)
- (path-join (getenv "objdir") "g10" name)))
+ (let ((name-ext (string-append name (getenv "EXEEXT"))))
+ (test::binary #f
+ (path-join "g10" name-ext)
+ (path-join (getenv "objdir") "g10" name-ext))))
(parse-makefile-expand (in-srcdir "g10" "Makefile.am")
(lambda (filename port key) (parse-makefile port key))
"module_tests")))
diff --git a/g10/armor.c b/g10/armor.c
index 7693483..b47c04a 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -247,6 +247,7 @@ is_armored (const byte *buf)
case PKT_COMPRESSED:
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
+ case PKT_ENCRYPTED_AEAD:
case PKT_PLAINTEXT:
case PKT_OLD_COMMENT:
case PKT_COMMENT:
@@ -649,6 +650,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
byte *p;
byte tempbuf[PARTIAL_CHUNK];
size_t tempbuf_len=0;
+ int this_truncated;
while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
/* copy what we have in the line buffer */
@@ -683,7 +685,13 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
continue;
}
if( !maxlen )
+ {
afx->truncated++;
+ this_truncated = 1;
+ }
+ else
+ this_truncated = 0;
+
p = afx->buffer;
n = afx->buffer_len;
@@ -736,7 +744,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
}
/* Now handle the end-of-line canonicalization */
- if( !afx->not_dash_escaped )
+ if( !afx->not_dash_escaped || this_truncated)
{
int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
@@ -753,10 +761,17 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
* or calculate the hash here in this module and somehow find
* a way to send the hash down the processing line (well, a special
* faked packet could do the job).
+ *
+ * To make sure that a truncated line triggers a bad
+ * signature error we replace a removed LF by a FF or
+ * append a FF. Right, this is a hack but better than a
+ * global variable and way easier than to introduce a new
+ * control packet or insert a line like "[truncated]\n"
+ * into the filter output.
*/
if( crlf )
afx->buffer[afx->buffer_len++] = '\r';
- afx->buffer[afx->buffer_len++] = '\n';
+ afx->buffer[afx->buffer_len++] = this_truncated? '\f':'\n';
afx->buffer[afx->buffer_len] = '\0';
}
}
@@ -1125,11 +1140,11 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
rc = 0;
else if( rc == 2 ) {
log_error(_("premature eof (in trailer)\n"));
- rc = GPG_ERR_INVALID_ARMOR;
+ rc = GPG_ERR_INV_ARMOR;
}
else {
log_error(_("error in trailer line\n"));
- rc = GPG_ERR_INVALID_ARMOR;
+ rc = GPG_ERR_INV_ARMOR;
}
#endif
}
@@ -1277,7 +1292,7 @@ armor_filter( void *opaque, int control,
if( !fp ) {
fp = fopen("armor.out", "w");
- assert(fp);
+ log_assert(fp);
}
#endif
@@ -1538,6 +1553,11 @@ armor_filter( void *opaque, int control,
afx->no_openpgp_data = 1;
write_status_text( STATUS_NODATA, "1" );
}
+ /* Note that in a cleartext signature truncated lines in the
+ * plaintext are detected and propagated to the signature
+ * checking code by inserting a \f into the plaintext. We do
+ * not use log_info here because some of the truncated lines
+ * are harmless. */
if( afx->truncated )
log_info(_("invalid armor: line longer than %d characters\n"),
MAX_LINELEN );
diff --git a/g10/build-packet.c b/g10/build-packet.c
index cc95355..f33d156 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -674,7 +674,8 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
count += 8; /* Salt. */
if (ski->s2k.mode == 3)
count++; /* S2K.COUNT */
- if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
+ if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002
+ && ski->s2k.mode != 1003)
count += ski->ivlen;
iobuf_put (a, count);
@@ -704,8 +705,9 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
if (ski->s2k.mode == 3)
iobuf_put (a, ski->s2k.count);
- /* For our special modes 1001, 1002 we do not need an IV. */
- if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
+ /* For our special modes 1001..1003 we do not need an IV. */
+ if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002
+ && ski->s2k.mode != 1003)
iobuf_write (a, ski->iv, ski->ivlen);
}
@@ -733,6 +735,22 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk)
/* The serial number gets stored in the IV field. */
iobuf_write (a, ski->iv, ski->ivlen);
}
+ else if (ski->s2k.mode == 1003)
+ {
+ /* GnuPG extension - Store raw s-expression. */
+ byte *p;
+ unsigned int ndatabits;
+
+ log_assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE));
+
+ p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits);
+ /* For v5 keys we first write the number of octets of the
+ * following key material. */
+ if (is_v5)
+ write_32 (a, p? (ndatabits+7)/8 : 0);
+ if (p)
+ iobuf_write (a, p, (ndatabits+7)/8 );
+ }
else if (ski->is_protected)
{
/* The secret key is protected - write it out as it is. */
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 27b5cac..66812e9 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -2997,13 +2997,15 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
keygrip, DESC a prompt to be displayed with the agent's passphrase
question (needs to be plus+percent escaped). if OPENPGP_PROTECTED
is not zero, ensure that the key material is returned in RFC
- 4880-compatible passphrased-protected form. If CACHE_NONCE_ADDR is
- not NULL the agent is advised to first try a passphrase associated
- with that nonce. On success the key is stored as a canonical
- S-expression at R_RESULT and R_RESULTLEN. */
+ 4880-compatible passphrased-protected form; if instead MODE1003 is
+ not zero the raw gpg-agent private key format is requested (either
+ protected or unprotected). If CACHE_NONCE_ADDR is not NULL the
+ agent is advised to first try a passphrase associated with that
+ nonce. On success the key is stored as a canonical S-expression at
+ R_RESULT and R_RESULTLEN. */
gpg_error_t
agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
- int openpgp_protected, char **cache_nonce_addr,
+ int openpgp_protected, int mode1003, char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen,
u32 *keyid, u32 *mainkeyid, int pubkey_algo)
{
@@ -3028,6 +3030,12 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
return err;
dfltparm.ctx = agent_ctx;
+ /* Check that the gpg-agent supports the --mode1003 option. */
+ if (mode1003 && assuan_transact (agent_ctx,
+ "GETINFO cmd_has_option EXPORT_KEY mode1003",
+ NULL, NULL, NULL, NULL, NULL, NULL))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
if (desc)
{
snprintf (line, DIM(line), "SETKEYDESC %s", desc);
@@ -3038,7 +3046,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
}
snprintf (line, DIM(line), "EXPORT_KEY %s%s%s %s",
- openpgp_protected ? "--openpgp ":"",
+ mode1003? "--mode1003" : openpgp_protected ? "--openpgp ":"",
cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
hexkeygrip);
diff --git a/g10/call-agent.h b/g10/call-agent.h
index a4cbc31..a3f234a 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -231,7 +231,7 @@ gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc,
/* Receive a key from the agent. */
gpg_error_t agent_export_key (ctrl_t ctrl, const char *keygrip,
const char *desc, int openpgp_protected,
- char **cache_nonce_addr,
+ int mode1003, char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen,
u32 *keyid, u32 *mainkeyid, int pubkey_algo);
diff --git a/g10/call-keyboxd.c b/g10/call-keyboxd.c
index e2fede2..7f4d5f4 100644
--- a/g10/call-keyboxd.c
+++ b/g10/call-keyboxd.c
@@ -106,7 +106,7 @@ gpg_keyboxd_deinit_session_data (ctrl_t ctrl)
err = assuan_transact (kbl->ctx, "TRANSACTION commit",
NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
- log_error ("error commiting last transaction: %s\n",
+ log_error ("error committing last transaction: %s\n",
gpg_strerror (err));
in_transaction = 0;
}
diff --git a/g10/card-util.c b/g10/card-util.c
index 339194f..02de241 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -843,7 +843,6 @@ change_name (void)
{
tty_printf (_("Error: Combined name too long "
"(limit is %d characters).\n"), 39);
- xfree (isoname);
rc = gpg_error (GPG_ERR_TOO_LARGE);
goto leave;
}
diff --git a/g10/cipher-aead.c b/g10/cipher-aead.c
index 8eea703..640d843 100644
--- a/g10/cipher-aead.c
+++ b/g10/cipher-aead.c
@@ -295,9 +295,9 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
size_t n1 = cfx->chunksize - (cfx->chunklen + cfx->buflen);
finalize = 1;
if (DBG_FILTER)
- log_debug ("chunksize %"PRIu64" reached;"
+ log_debug ("chunksize %llu reached;"
" cur buflen=%zu using %zu of %zu\n",
- cfx->chunksize, cfx->buflen,
+ (unsigned long long)cfx->chunksize, cfx->buflen,
n1, n);
n = n1;
}
diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index bdc3e22..86e208d 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -675,8 +675,10 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
/* Decrypt the buffer. This first requires a loop to handle the
* case when a chunk ends within the buffer. */
if (DBG_FILTER)
- log_debug ("decrypt: chunklen=%"PRIu64" total=%"PRIu64" size=%zu len=%zu%s\n",
- dfx->chunklen, dfx->total, size, len,
+ log_debug ("decrypt: chunklen=%llu total=%llu size=%zu len=%zu%s\n",
+ (unsigned long long)dfx->chunklen,
+ (unsigned long long)dfx->total,
+ size, len,
dfx->eof_seen? " eof":"");
while (len && dfx->chunklen + len >= dfx->chunksize)
@@ -712,8 +714,8 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
len -= n;
if (DBG_FILTER)
- log_debug ("ndecrypted: %zu (nchunk=%"PRIu64") bytes left: %zu at off=%zu\n",
- totallen, dfx->chunklen, len, off);
+ log_debug ("ndecrypted: %zu (nchunk=%llu) bytes left: %zu at off=%zu\n",
+ totallen, (unsigned long long)dfx->chunklen, len, off);
/* Check the tag. */
if (len < 16)
@@ -794,8 +796,8 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
dfx->chunklen += len;
dfx->total += len;
if (DBG_FILTER)
- log_debug ("ndecrypted: %zu (nchunk=%"PRIu64")\n",
- totallen, dfx->chunklen);
+ log_debug ("ndecrypted: %zu (nchunk=%llu)\n",
+ totallen, (unsigned long long)dfx->chunklen);
}
if (dfx->eof_seen)
diff --git a/g10/ecdh.c b/g10/ecdh.c
index c3337d1..eb14154 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -189,6 +189,28 @@ derive_kek (size_t kek_size,
const unsigned char *kdf_params, size_t kdf_params_size)
{
gpg_error_t err;
+#if 0 /* GCRYPT_VERSION_NUMBER >= 0x010b00 */
+ /*
+ * Experimental: We will remove this if/endif-conditional
+ * compilation when we update NEED_LIBGCRYPT_VERSION to 1.11.0.
+ */
+ gcry_kdf_hd_t hd;
+ unsigned long param[1];
+
+ param[0] = kek_size;
+ err = gcry_kdf_open (&hd, GCRY_KDF_ONESTEP_KDF, kdf_hash_algo,
+ param, 1,
+ secret_x, secret_x_size, NULL, 0, NULL, 0,
+ kdf_params, kdf_params_size);
+ if (!err)
+ {
+ gcry_kdf_compute (hd, NULL);
+ gcry_kdf_final (hd, kek_size, secret_x);
+ gcry_kdf_close (hd);
+ /* Clean the tail before returning. */
+ memset (secret_x+kek_size, 0, secret_x_size - kek_size);
+ }
+#else
gcry_md_hd_t h;
log_assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 );
@@ -208,6 +230,7 @@ derive_kek (size_t kek_size,
gcry_md_close (h);
/* Clean the tail before returning. */
memset (secret_x+kek_size, 0, secret_x_size - kek_size);
+#endif
if (DBG_CRYPTO)
log_printhex (secret_x, kek_size, "ecdh KEK is:");
return err;
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 019bf0b..d0e1427 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -219,7 +219,7 @@ check_encryption_compliance (DEK *dek, pk_list_t pk_list)
* stored at R_SESKEY. If AEAD_ALGO is not 0 the given AEAD algorithm
* is used for encryption.
*/
-gpg_error_t
+static gpg_error_t
encrypt_seskey (DEK *dek, aead_algo_t aead_algo,
DEK **r_seskey, void **r_enckey, size_t *r_enckeylen)
{
@@ -344,14 +344,6 @@ use_aead (pk_list_t pk_list, int algo)
{
int can_use;
- if (!opt.flags.rfc4880bis)
- {
- if (opt.force_aead)
- log_info ("Warning: Option %s currently requires option '%s'\n",
- "--force-aead", "--rfc4880bis");
- return 0;
- }
-
can_use = openpgp_cipher_get_algo_blklen (algo) == 16;
/* With --force-aead we want AEAD. */
@@ -359,11 +351,11 @@ use_aead (pk_list_t pk_list, int algo)
{
if (!can_use)
{
- log_info ("Warning: request to use AEAD ignored for cipher '%s'\n",
+ log_info ("Warning: request to use OCB ignored for cipher '%s'\n",
openpgp_cipher_algo_name (algo));
return 0;
}
- return default_aead_algo ();
+ return AEAD_ALGO_OCB;
}
/* AEAD does only work with 128 bit cipher blocklength. */
@@ -478,8 +470,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
if (use_seskey && s2k->mode != 1 && s2k->mode != 3)
{
use_seskey = 0;
- log_info (_("can't use a symmetric ESK packet "
- "due to the S2K mode\n"));
+ log_info (_("can't use a SKESK packet due to the S2K mode\n"));
}
/* See whether we want to use AEAD. */
diff --git a/g10/exec.c b/g10/exec.c
index 75b39e0..3189fff 100644
--- a/g10/exec.c
+++ b/g10/exec.c
@@ -19,12 +19,6 @@
#include <config.h>
#include <stdlib.h>
-#ifdef HAVE_DOSISH_SYSTEM
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
-# include <windows.h>
-#endif
#include <string.h>
#include "gpg.h"
@@ -35,115 +29,6 @@
#ifdef NO_EXEC
int set_exec_path(const char *path) { return GPG_ERR_GENERAL; }
#else
-#if defined (_WIN32)
-/* This is a nicer system() for windows that waits for programs to
- return before returning control to the caller. I hate helpful
- computers. */
-int
-w32_system(const char *command)
-{
- if (!strncmp (command, "!ShellExecute ", 14))
- {
- SHELLEXECUTEINFOW see;
- wchar_t *wname;
- int waitms;
-
- command = command + 14;
- while (spacep (command))
- command++;
- waitms = atoi (command);
- if (waitms < 0)
- waitms = 0;
- else if (waitms > 60*1000)
- waitms = 60000;
- while (*command && !spacep (command))
- command++;
- while (spacep (command))
- command++;
-
- wname = utf8_to_wchar (command);
- if (!wname)
- return -1;
-
- memset (&see, 0, sizeof see);
- see.cbSize = sizeof see;
- see.fMask = (SEE_MASK_NOCLOSEPROCESS
- | SEE_MASK_NOASYNC
- | SEE_MASK_FLAG_NO_UI
- | SEE_MASK_NO_CONSOLE);
- see.lpVerb = L"open";
- see.lpFile = (LPCWSTR)wname;
- see.nShow = SW_SHOW;
-
- if (DBG_EXTPROG)
- log_debug ("running ShellExecuteEx(open,'%s')\n", command);
- if (!ShellExecuteExW (&see))
- {
- if (DBG_EXTPROG)
- log_debug ("ShellExecuteEx failed: rc=%d\n", (int)GetLastError ());
- xfree (wname);
- return -1;
- }
- if (DBG_EXTPROG)
- log_debug ("ShellExecuteEx succeeded (hProcess=%p,hInstApp=%d)\n",
- see.hProcess, (int)see.hInstApp);
-
- if (!see.hProcess)
- {
- gnupg_usleep (waitms*1000);
- if (DBG_EXTPROG)
- log_debug ("ShellExecuteEx ready (wait=%dms)\n", waitms);
- }
- else
- {
- WaitForSingleObject (see.hProcess, INFINITE);
- if (DBG_EXTPROG)
- log_debug ("ShellExecuteEx ready\n");
- }
- CloseHandle (see.hProcess);
-
- xfree (wname);
- }
- else
- {
- char *string;
- wchar_t *wstring;
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
-
- /* We must use a copy of the command as CreateProcess modifies
- * this argument. */
- string = xstrdup (command);
- wstring = utf8_to_wchar (string);
- xfree (string);
- if (!wstring)
- return -1;
-
- memset (&pi, 0, sizeof(pi));
- memset (&si, 0, sizeof(si));
- si.cb = sizeof (si);
-
- if (!CreateProcessW (NULL, wstring, NULL, NULL, FALSE,
- DETACHED_PROCESS,
- NULL, NULL, &si, &pi))
- {
- xfree (wstring);
- return -1;
- }
-
- /* Wait for the child to exit */
- WaitForSingleObject (pi.hProcess, INFINITE);
-
- CloseHandle (pi.hProcess);
- CloseHandle (pi.hThread);
- xfree (wstring);
- }
-
- return 0;
-}
-#endif /*_W32*/
-
-
/* Replaces current $PATH */
int
set_exec_path(const char *path)
diff --git a/g10/exec.h b/g10/exec.h
index 6b24d1c..b3f96cf 100644
--- a/g10/exec.h
+++ b/g10/exec.h
@@ -21,6 +21,5 @@
#define _EXEC_H_
int set_exec_path(const char *path);
-int w32_system(const char *command);
#endif /* !_EXEC_H_ */
diff --git a/g10/export.c b/g10/export.c
index edf27bc..b3ad697 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -2,6 +2,7 @@
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005, 2010 Free Software Foundation, Inc.
* Copyright (C) 1998-2016 Werner Koch
+ * Copyright (C) 2022 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -63,15 +64,17 @@ struct export_stats_s
};
-/* A global variable to store the selector created from
+/* Global variables to store the selectors created from
* --export-filter keep-uid=EXPR.
* --export-filter drop-subkey=EXPR.
+ * --export-filter select=EXPR.
*
* FIXME: We should put this into the CTRL object but that requires a
* lot more changes right now.
*/
static recsel_expr_t export_keep_uid;
static recsel_expr_t export_drop_subkey;
+static recsel_expr_t export_select_filter;
/* An object used for a linked list to implement the
@@ -81,6 +84,7 @@ struct export_filter_attic_s
struct export_filter_attic_s *next;
recsel_expr_t export_keep_uid;
recsel_expr_t export_drop_subkey;
+ recsel_expr_t export_select_filter;
};
static struct export_filter_attic_s *export_filter_attic;
@@ -105,6 +109,8 @@ cleanup_export_globals (void)
export_keep_uid = NULL;
recsel_release (export_drop_subkey);
export_drop_subkey = NULL;
+ recsel_release (export_select_filter);
+ export_select_filter = NULL;
}
@@ -128,10 +134,16 @@ parse_export_options(char *str,unsigned int *options,int noisy)
{"export-dane", EXPORT_DANE_FORMAT, NULL, NULL },
+ {"export-revocs", EXPORT_REVOCS, NULL,
+ N_("export only revocation certificates") },
+
{"backup", EXPORT_BACKUP, NULL,
N_("use the GnuPG key backup format")},
{"export-backup", EXPORT_BACKUP, NULL, NULL },
+ {"mode1003", EXPORT_MODE1003, NULL,
+ N_("export secret keys using the GnuPG format") },
+
/* Aliases for backward compatibility */
{"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
{"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
@@ -184,6 +196,8 @@ parse_export_options(char *str,unsigned int *options,int noisy)
*
* - secret :: 1 for a secret subkey, else 0.
* - key_algo :: Public key algorithm id
+ *
+ * - select :: The key is only exported if the filter returns true.
*/
gpg_error_t
parse_and_set_export_filter (const char *string)
@@ -197,6 +211,8 @@ parse_and_set_export_filter (const char *string)
err = recsel_parse_expr (&export_keep_uid, string+9);
else if (!strncmp (string, "drop-subkey=", 12))
err = recsel_parse_expr (&export_drop_subkey, string+12);
+ else if (!strncmp (string, "select=", 7))
+ err = recsel_parse_expr (&export_select_filter, string+7);
else
err = gpg_error (GPG_ERR_INV_NAME);
@@ -217,6 +233,8 @@ push_export_filters (void)
export_keep_uid = NULL;
item->export_drop_subkey = export_drop_subkey;
export_drop_subkey = NULL;
+ item->export_select_filter = export_select_filter;
+ export_select_filter = NULL;
item->next = export_filter_attic;
export_filter_attic = item;
}
@@ -235,6 +253,7 @@ pop_export_filters (void)
cleanup_export_globals ();
export_keep_uid = item->export_keep_uid;
export_drop_subkey = item->export_drop_subkey;
+ export_select_filter = item->export_select_filter;
}
@@ -624,6 +643,183 @@ canon_pk_algo (enum gcry_pk_algos algo)
}
+/* Take an s-expression wit the public and private key and change the
+ * parameter array in PK to include the secret parameters. */
+static gpg_error_t
+secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk)
+{
+ gpg_error_t err;
+ gcry_sexp_t list = NULL;
+ gcry_sexp_t l2;
+ enum gcry_pk_algos pk_algo;
+ struct seckey_info *ski;
+ int idx;
+ char *string;
+ size_t npkey, nskey;
+ gcry_mpi_t pub_params[10] = { NULL };
+
+ /* We look for a private-key, then the first element in it tells us
+ the type */
+ list = gcry_sexp_find_token (s_key, "protected-private-key", 0);
+ if (!list)
+ list = gcry_sexp_find_token (s_key, "private-key", 0);
+ if (!list)
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+
+ log_assert (!pk->seckey_info);
+
+ /* Parse the gcrypt PK algo and check that it is okay. */
+ l2 = gcry_sexp_cadr (list);
+ if (!l2)
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+ gcry_sexp_release (list);
+ list = l2;
+ string = gcry_sexp_nth_string (list, 0);
+ if (!string)
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+ pk_algo = gcry_pk_map_name (string);
+ xfree (string); string = NULL;
+ if (gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
+ || gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
+ || !npkey || npkey >= nskey)
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+
+ /* Check that the pubkey algo and the received parameters matches
+ * those from the public key. */
+ switch (canon_pk_algo (pk_algo))
+ {
+ case GCRY_PK_RSA:
+ if (!is_RSA (pk->pubkey_algo) || npkey != 2)
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
+ else
+ err = gcry_sexp_extract_param (list, NULL, "ne",
+ &pub_params[0],
+ &pub_params[1],
+ NULL);
+ break;
+
+ case GCRY_PK_DSA:
+ if (!is_DSA (pk->pubkey_algo) || npkey != 4)
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
+ else
+ err = gcry_sexp_extract_param (list, NULL, "pqgy",
+ &pub_params[0],
+ &pub_params[1],
+ &pub_params[2],
+ &pub_params[3],
+ NULL);
+ break;
+
+ case GCRY_PK_ELG:
+ if (!is_ELGAMAL (pk->pubkey_algo) || npkey != 3)
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
+ else
+ err = gcry_sexp_extract_param (list, NULL, "pgy",
+ &pub_params[0],
+ &pub_params[1],
+ &pub_params[2],
+ NULL);
+ break;
+
+ case GCRY_PK_ECC:
+ err = 0;
+ if (!(pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH
+ || pk->pubkey_algo == PUBKEY_ALGO_EDDSA))
+ {
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
+ goto leave;
+ }
+ npkey = 2;
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
+ npkey++;
+ /* Dedicated check of the curve. */
+ pub_params[0] = NULL;
+ err = match_curve_skey_pk (list, pk);
+ if (err)
+ goto leave;
+ /* ... and of the Q parameter. */
+ err = sexp_extract_param_sos (list, "q", &pub_params[1]);
+ if (!err && (gcry_mpi_cmp (pk->pkey[1], pub_params[1])))
+ err = gpg_error (GPG_ERR_BAD_PUBKEY);
+ break;
+
+ default:
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Unknown. */
+ break;
+ }
+ if (err)
+ goto leave;
+
+ nskey = npkey + 1; /* We only have one skey param. */
+ if (nskey > PUBKEY_MAX_NSKEY)
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+
+ /* Check that the public key parameters match. For ECC we already
+ * did this in the switch above. */
+ if (canon_pk_algo (pk_algo) != GCRY_PK_ECC)
+ {
+ for (idx=0; idx < npkey; idx++)
+ if (gcry_mpi_cmp (pk->pkey[idx], pub_params[idx]))
+ {
+ err = gpg_error (GPG_ERR_BAD_PUBKEY);
+ goto leave;
+ }
+ }
+
+ /* Store the maybe protected secret key as an s-expression. */
+ pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
+ if (!ski)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
+ if (!ski)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ ski->is_protected = 1;
+ ski->s2k.mode = 1003;
+
+ {
+ unsigned char *buf;
+ size_t buflen;
+
+ err = make_canon_sexp (s_key, &buf, &buflen);
+ if (err)
+ goto leave;
+ pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, buf, buflen*8);
+ for (idx=npkey+1; idx < PUBKEY_MAX_NSKEY; idx++)
+ pk->pkey[idx] = NULL;
+ }
+
+ leave:
+ gcry_sexp_release (list);
+ for (idx=0; idx < DIM(pub_params); idx++)
+ gcry_mpi_release (pub_params[idx]);
+ return err;
+}
+
+
/* Take a cleartext dump of a secret key in PK and change the
* parameter array in PK to include the secret parameters. */
static gpg_error_t
@@ -1233,29 +1429,51 @@ print_status_exported (PKT_public_key *pk)
* passphrase-protected. Otherwise, store secret key material in the
* clear.
*
+ * If MODE1003 is set, the key is requested in raw GnuPG format from
+ * the agent. This usually does not require a passphrase unless the
+ * gpg-agent has not yet used the key and needs to convert it to its
+ * internal format first.
+ *
* CACHE_NONCE_ADDR is used to share nonce for multiple key retrievals.
+ *
+ * If PK is NULL, the raw key is returned (e.g. for ssh export) at
+ * R_KEY. CLEARTEXT and CACHE_NONCE_ADDR ared ignored in this case.
*/
gpg_error_t
receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
- int cleartext,
+ int cleartext, int mode1003,
char **cache_nonce_addr, const char *hexgrip,
- PKT_public_key *pk)
+ PKT_public_key *pk, gcry_sexp_t *r_key)
{
gpg_error_t err = 0;
unsigned char *wrappedkey = NULL;
size_t wrappedkeylen;
unsigned char *key = NULL;
size_t keylen, realkeylen;
- gcry_sexp_t s_skey;
+ gcry_sexp_t s_skey = NULL;
char *prompt;
+ if (r_key)
+ *r_key = NULL;
if (opt.verbose)
log_info ("key %s: asking agent for the secret parts\n", hexgrip);
- prompt = gpg_format_keydesc (ctrl, pk, FORMAT_KEYDESC_EXPORT,1);
- err = agent_export_key (ctrl, hexgrip, prompt, !cleartext, cache_nonce_addr,
- &wrappedkey, &wrappedkeylen,
- pk->keyid, pk->main_keyid, pk->pubkey_algo);
+ if (pk)
+ {
+ prompt = gpg_format_keydesc (ctrl, pk, FORMAT_KEYDESC_EXPORT, 1);
+ err = agent_export_key (ctrl, hexgrip, prompt, !cleartext, mode1003,
+ cache_nonce_addr,
+ &wrappedkey, &wrappedkeylen,
+ pk->keyid, pk->main_keyid, pk->pubkey_algo);
+ }
+ else
+ {
+ prompt = gpg_format_keydesc (ctrl, NULL, FORMAT_KEYDESC_KEYGRIP, 1);
+ err = agent_export_key (ctrl, hexgrip, prompt, 0, 0,
+ NULL,
+ &wrappedkey, &wrappedkeylen,
+ NULL, NULL, 0);
+ }
xfree (prompt);
if (err)
@@ -1282,14 +1500,21 @@ receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
if (!err)
{
- if (cleartext)
+ if (pk && mode1003)
+ err = secret_key_to_mode1003 (s_skey, pk);
+ else if (pk && cleartext)
err = cleartext_secret_key_to_openpgp (s_skey, pk);
- else
+ else if (pk)
err = transfer_format_to_openpgp (s_skey, pk);
- gcry_sexp_release (s_skey);
+ else if (r_key)
+ {
+ *r_key = s_skey;
+ s_skey = NULL;
+ }
}
unwraperror:
+ gcry_sexp_release (s_skey);
xfree (key);
xfree (wrappedkey);
if (err)
@@ -1795,11 +2020,22 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
else if (!err)
{
err = receive_seckey_from_agent (ctrl, cipherhd,
- cleartext, &cache_nonce,
- hexgrip, pk);
+ cleartext,
+ !!(options & EXPORT_MODE1003),
+ &cache_nonce,
+ hexgrip, pk, NULL);
if (err)
{
- if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
+ /* If we receive a fully canceled error we stop
+ * immediately. If we receive a cancel for a public
+ * key we also stop immediately because a
+ * public/secret key is always required first
+ * (right, we could instead write a stub key but
+ * that is also kind of surprising). If we receive
+ * a subkey we skip to the next subkey. */
+ if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED
+ || (node->pkt->pkttype == PKT_PUBLIC_KEY
+ && gpg_err_code (err) == GPG_ERR_CANCELED))
goto leave;
write_status_error ("export_keys.secret", err);
skip_until_subkey = 1;
@@ -1872,6 +2108,78 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
}
+/* Helper for do_export_stream which writes the own revocations
+ * certificates (if any) from KEYBLOCK to OUT. */
+static gpg_error_t
+do_export_revocs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
+ iobuf_t out, unsigned int options, int *any)
+{
+ gpg_error_t err = 0;
+ kbnode_t kbctx, node;
+ PKT_signature *sig;
+
+ (void)ctrl;
+
+ /* NB: walk_kbnode skips packets marked as deleted. */
+ for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+ {
+ if (node->pkt->pkttype != PKT_SIGNATURE)
+ continue;
+ sig = node->pkt->pkt.signature;
+
+ /* We are only interested in revocation certifcates. */
+ if (!(IS_KEY_REV (sig) || IS_UID_REV (sig) || IS_SUBKEY_REV (sig)))
+ continue;
+
+ if (!(sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1]))
+ continue; /* Not a self-signature. */
+
+ /* Do not export signature packets which are marked as not
+ * exportable. */
+ if (!(options & EXPORT_LOCAL_SIGS)
+ && !sig->flags.exportable)
+ continue; /* not exportable */
+
+ /* Do not export packets with a "sensitive" revocation key
+ * unless the user wants us to. */
+ if (!(options & EXPORT_SENSITIVE_REVKEYS)
+ && sig->revkey)
+ {
+ int i;
+
+ for (i = 0; i < sig->numrevkeys; i++)
+ if ((sig->revkey[i].class & 0x40))
+ break;
+ if (i < sig->numrevkeys)
+ continue;
+ }
+
+ if (!sig->flags.checked)
+ {
+ log_info ("signature not marked as checked - ignored\n");
+ continue;
+ }
+ if (!sig->flags.valid)
+ {
+ log_info ("signature not not valid - ignored\n");
+ continue;
+ }
+
+ err = build_packet (out, node->pkt);
+ if (err)
+ {
+ log_error ("build_packet(%d) failed: %s\n",
+ node->pkt->pkttype, gpg_strerror (err));
+ goto leave;
+ }
+ *any = 1;
+ }
+
+ leave:
+ return err;
+}
+
+
/* For secret key export we need to setup a decryption context.
* Returns 0 and the context at r_cipherhd. */
static gpg_error_t
@@ -2066,13 +2374,33 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
NULL, NULL);
commit_kbnode (&keyblock);
}
- else if (export_keep_uid || export_drop_subkey)
+ else if (export_keep_uid || export_drop_subkey || export_select_filter)
{
/* Need to merge so that for example the "usage" property
* has been setup. */
merge_keys_and_selfsig (ctrl, keyblock);
}
+
+ if (export_select_filter)
+ {
+ int selected = 0;
+ struct impex_filter_parm_s parm;
+ parm.ctrl = ctrl;
+
+ for (parm.node = keyblock; parm.node; parm.node = parm.node->next)
+ {
+ if (recsel_select (export_select_filter,
+ impex_filter_getval, &parm))
+ {
+ selected = 1;
+ break;
+ }
+ }
+ if (!selected)
+ continue; /* Skip this keyblock. */
+ }
+
if (export_keep_uid)
{
commit_kbnode (&keyblock);
@@ -2088,10 +2416,15 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
}
/* And write it. */
- err = do_export_one_keyblock (ctrl, keyblock, keyid,
- out_help? out_help : out,
- secret, options, stats, any,
- desc, ndesc, descindex, cipherhd);
+ if ((options & EXPORT_REVOCS))
+ err = do_export_revocs (ctrl, keyblock, keyid,
+ out_help? out_help : out,
+ options, any);
+ else
+ err = do_export_one_keyblock (ctrl, keyblock, keyid,
+ out_help? out_help : out,
+ secret, options, stats, any,
+ desc, ndesc, descindex, cipherhd);
if (err)
break;
@@ -2131,8 +2464,8 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
keydb_release (kdbhd);
if (err || !keyblock_out)
release_kbnode( keyblock );
- if( !*any )
- log_info(_("WARNING: nothing exported\n"));
+ if( !*any && !opt.quiet)
+ log_info (_("WARNING: nothing exported\n"));
return err;
}
@@ -2602,74 +2935,6 @@ export_ssh_key (ctrl_t ctrl, const char *userid)
}
-/* Simplified version of receive_seckey_from_agent used to get the raw
- * key. */
-gpg_error_t
-receive_raw_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
- const char *hexgrip, gcry_sexp_t *r_key)
-{
- gpg_error_t err = 0;
- unsigned char *wrappedkey = NULL;
- size_t wrappedkeylen;
- unsigned char *key = NULL;
- size_t keylen, realkeylen;
- gcry_sexp_t s_skey = NULL;
-
- *r_key = NULL;
- if (opt.verbose)
- log_info ("key %s: asking agent for the secret parts\n", hexgrip);
-
- {
- char * prompt = gpg_format_keydesc (ctrl, NULL, FORMAT_KEYDESC_KEYGRIP, 1);
- err = agent_export_key (ctrl, hexgrip, prompt, 0, NULL,
- &wrappedkey, &wrappedkeylen,
- NULL, NULL, 0);
- xfree (prompt);
- }
- if (err)
- goto leave;
-
- if (wrappedkeylen < 24)
- {
- err = gpg_error (GPG_ERR_INV_LENGTH);
- goto leave;
- }
- keylen = wrappedkeylen - 8;
- key = xtrymalloc_secure (keylen);
- if (!key)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
- err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
- if (err)
- goto leave;
- realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
- if (!realkeylen)
- goto leave; /* Invalid csexp. */
-
- err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
- if (!err)
- {
- gcry_log_debugsxp ("skey", s_skey);
- *r_key = s_skey;
- s_skey = NULL;
- }
-
- leave:
- gcry_sexp_release (s_skey);
- xfree (key);
- xfree (wrappedkey);
- if (err)
- {
- log_error ("key %s: error receiving key from agent:"
- " %s%s\n", hexgrip, gpg_strerror (err),
- "");
- }
- return err;
-}
-
-
/* Export the key identified by USERID in the SSH secret key format.
* The USERID must be given in keygrip format (prefixed with a '&')
* and thus no OpenPGP key is required. The exported key is not
@@ -2715,7 +2980,8 @@ export_secret_ssh_key (ctrl_t ctrl, const char *userid)
if ((err = get_keywrap_key (ctrl, &cipherhd)))
goto leave;
- err = receive_raw_seckey_from_agent (ctrl, cipherhd, hexgrip, &skey);
+ err = receive_seckey_from_agent (ctrl, cipherhd, 0, 0, NULL, hexgrip, NULL,
+ &skey);
if (err)
goto leave;
diff --git a/g10/gpg.c b/g10/gpg.c
index 35ffaf3..68c0454 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1,7 +1,7 @@
/* gpg.c - The GnuPG OpenPGP tool
* Copyright (C) 1998-2020 Free Software Foundation, Inc.
* Copyright (C) 1997-2019 Werner Koch
- * Copyright (C) 2015-2021 g10 Code GmbH
+ * Copyright (C) 2015-2022 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -133,6 +133,7 @@ enum cmd_and_opt_values
aQuickRevUid,
aQuickSetExpire,
aQuickSetPrimaryUid,
+ aQuickUpdatePref,
aListConfig,
aListGcryptConfig,
aGPGConfList,
@@ -245,7 +246,6 @@ enum cmd_and_opt_values
oGnuPG,
oRFC2440,
oRFC4880,
- oRFC4880bis,
oOpenPGP,
oPGP7,
oPGP8,
@@ -254,7 +254,6 @@ enum cmd_and_opt_values
oRFC2440Text,
oNoRFC2440Text,
oCipherAlgo,
- oAEADAlgo,
oDigestAlgo,
oCertDigestAlgo,
oCompressAlgo,
@@ -328,6 +327,7 @@ enum cmd_and_opt_values
oExportOptions,
oExportFilter,
oListOptions,
+ oListFilter,
oVerifyOptions,
oTempDir,
oExecPath,
@@ -383,7 +383,6 @@ enum cmd_and_opt_values
oDefaultPreferenceList,
oDefaultKeyserverURL,
oPersonalCipherPreferences,
- oPersonalAEADPreferences,
oPersonalDigestPreferences,
oPersonalCompressPreferences,
oAgentProgram,
@@ -444,6 +443,7 @@ enum cmd_and_opt_values
oForceSignKey,
oForbidGenKey,
oRequireCompliance,
+ oCompatibilityFlags,
oNoop
};
@@ -491,6 +491,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_c (aQuickSetExpire, "quick-set-expire",
N_("quickly set a new expiration date")),
ARGPARSE_c (aQuickSetPrimaryUid, "quick-set-primary-uid", "@"),
+ ARGPARSE_c (aQuickUpdatePref, "quick-update-pref", "@"),
ARGPARSE_c (aFullKeygen, "full-generate-key" ,
N_("full featured key pair generation")),
ARGPARSE_c (aFullKeygen, "full-gen-key", "@"),
@@ -629,7 +630,6 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oGnuPG, "no-pgp8", "@"),
ARGPARSE_s_n (oRFC2440, "rfc2440", "@"),
ARGPARSE_s_n (oRFC4880, "rfc4880", "@"),
- ARGPARSE_s_n (oRFC4880bis, "rfc4880bis", "@"),
ARGPARSE_s_n (oOpenPGP, "openpgp", N_("use strict OpenPGP behavior")),
ARGPARSE_s_n (oPGP7, "pgp6", "@"),
ARGPARSE_s_n (oPGP7, "pgp7", "@"),
@@ -674,7 +674,6 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oEnableDSA2, "enable-dsa2", "@"),
ARGPARSE_s_n (oDisableDSA2, "disable-dsa2", "@"),
ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-preferences","@"),
- ARGPARSE_s_s (oPersonalAEADPreferences, "personal-aead-preferences","@"),
ARGPARSE_s_s (oPersonalDigestPreferences, "personal-digest-preferences","@"),
ARGPARSE_s_s (oPersonalCompressPreferences,
"personal-compress-preferences", "@"),
@@ -796,6 +795,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_header ("Keylist", N_("Options controlling key listings")),
ARGPARSE_s_s (oListOptions, "list-options", "@"),
+ ARGPARSE_s_s (oListFilter, "list-filter", "@"),
ARGPARSE_s_n (oFullTimestrings, "full-timestrings", "@"),
ARGPARSE_s_n (oShowPhotos, "show-photos", "@"),
ARGPARSE_s_n (oNoShowPhotos, "no-show-photos", "@"),
@@ -854,7 +854,8 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_s (oS2KDigest, "s2k-digest-algo", "@"),
ARGPARSE_s_s (oS2KCipher, "s2k-cipher-algo", "@"),
ARGPARSE_s_i (oS2KCount, "s2k-count", "@"),
- ARGPARSE_s_n (oForceAEAD, "force-aead", "@"),
+ ARGPARSE_s_n (oForceAEAD, "force-ocb", "@"),
+ ARGPARSE_s_n (oForceAEAD, "force-aead", "@"), /*(old name)*/
ARGPARSE_s_n (oRequireCrossCert, "require-backsigs", "@"),
ARGPARSE_s_n (oRequireCrossCert, "require-cross-certification", "@"),
ARGPARSE_s_n (oNoRequireCrossCert, "no-require-backsigs", "@"),
@@ -875,7 +876,6 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_s (oDisableCipherAlgo, "disable-cipher-algo", "@"),
ARGPARSE_s_s (oDisablePubkeyAlgo, "disable-pubkey-algo", "@"),
ARGPARSE_s_s (oCipherAlgo, "cipher-algo", "@"),
- ARGPARSE_s_s (oAEADAlgo, "aead-algo", "@"),
ARGPARSE_s_s (oDigestAlgo, "digest-algo", "@"),
ARGPARSE_s_s (oCertDigestAlgo, "cert-digest-algo", "@"),
ARGPARSE_s_n (oOverrideComplianceCheck, "override-compliance-check", "@"),
@@ -914,6 +914,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oUseKeyboxd, "use-keyboxd", "@"),
ARGPARSE_s_n (oForbidGenKey, "forbid-gen-key", "@"),
ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"),
+ ARGPARSE_s_s (oCompatibilityFlags, "compatibility-flags", "@"),
/* Options which can be used in special circumstances. They are not
* published and we hope they are never required. */
ARGPARSE_s_n (oUseOnlyOpenPGPCard, "use-only-openpgp-card", "@"),
@@ -926,8 +927,6 @@ static gpgrt_opt_t opts[] = {
/* Aliases. I constantly mistype these, and assume other people do
as well. */
ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-prefs", "@"),
- ARGPARSE_s_s (oPersonalAEADPreferences, "personal-aead-prefs", "@"),
- ARGPARSE_s_s (oPersonalDigestPreferences, "personal-digest-prefs", "@"),
ARGPARSE_s_s (oPersonalCompressPreferences, "personal-compress-prefs", "@"),
/* These two are aliases to help users of the PGP command line
@@ -970,6 +969,9 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oNoop, "allow-multisig-verification", "@"),
ARGPARSE_s_n (oNoop, "allow-multiple-messages", "@"),
ARGPARSE_s_n (oNoop, "no-allow-multiple-messages", "@"),
+ ARGPARSE_s_s (oNoop, "aead-algo", "@"),
+ ARGPARSE_s_s (oNoop, "personal-aead-preferences","@"),
+ ARGPARSE_s_n (oNoop, "rfc4880bis", "@"),
ARGPARSE_group (302, N_(
@@ -1009,6 +1011,13 @@ static struct debug_flags_s debug_flags [] =
};
+/* The list of compatibility flags. */
+static struct compatibility_flags_s compatibility_flags [] =
+ {
+ { 0, NULL }
+ };
+
+
#ifdef ENABLE_SELINUX_HACKS
#define ALWAYS_ADD_KEYRINGS 1
#else
@@ -1104,18 +1113,6 @@ build_list_cipher_algo_name (int algo)
}
static int
-build_list_aead_test_algo (int algo)
-{
- return openpgp_aead_test_algo (algo);
-}
-
-static const char *
-build_list_aead_algo_name (int algo)
-{
- return openpgp_aead_algo_name (algo);
-}
-
-static int
build_list_md_test_algo (int algo)
{
/* By default we do not accept MD5 based signatures. To avoid
@@ -1136,7 +1133,7 @@ build_list_md_algo_name (int algo)
static const char *
my_strusage( int level )
{
- static char *digests, *pubkeys, *ciphers, *zips, *aeads, *ver_gcry;
+ static char *digests, *pubkeys, *ciphers, *zips, *ver_gcry;
const char *p;
switch( level ) {
@@ -1198,13 +1195,6 @@ my_strusage( int level )
build_list_cipher_test_algo );
p = ciphers;
break;
- case 36:
- if (!aeads)
- aeads = build_list ("AEAD: ", 'A',
- build_list_aead_algo_name,
- build_list_aead_test_algo);
- p = aeads;
- break;
case 37:
if( !digests )
digests = build_list(_("Hash: "), 'H',
@@ -2084,6 +2074,10 @@ parse_list_options(char *str)
N_("show the keyring name in key listings")},
{"show-sig-expire",LIST_SHOW_SIG_EXPIRE,NULL,
N_("show expiration dates during signature listings")},
+ {"show-pref", LIST_SHOW_PREF, NULL,
+ N_("show preferences")},
+ {"show-pref-verbose", LIST_SHOW_PREF_VERBOSE, NULL,
+ N_("show preferences")},
{"show-sig-subpackets",LIST_SHOW_SIG_SUBPACKETS,NULL,
NULL},
{"show-only-fpr-mbox",LIST_SHOW_ONLY_FPR_MBOX, NULL,
@@ -2211,7 +2205,7 @@ static struct gnupg_compliance_option compliance_options[] =
{
{ "gnupg", oGnuPG },
{ "openpgp", oOpenPGP },
- { "rfc4880bis", oRFC4880bis },
+ { "rfc4880bis", oGnuPG },
{ "rfc4880", oRFC4880 },
{ "rfc2440", oRFC2440 },
{ "pgp6", oPGP7 },
@@ -2227,29 +2221,8 @@ static struct gnupg_compliance_option compliance_options[] =
static void
set_compliance_option (enum cmd_and_opt_values option)
{
- opt.flags.rfc4880bis = 0; /* Clear because it is initially set. */
-
switch (option)
{
- case oRFC4880bis:
- opt.flags.rfc4880bis = 1;
- opt.compliance = CO_RFC4880;
- opt.flags.dsa2 = 1;
- opt.flags.require_cross_cert = 1;
- opt.rfc2440_text = 0;
- opt.allow_non_selfsigned_uid = 1;
- opt.allow_freeform_uid = 1;
- opt.escape_from = 1;
- opt.not_dash_escaped = 0;
- opt.def_cipher_algo = 0;
- opt.def_aead_algo = 0;
- opt.def_digest_algo = 0;
- opt.cert_digest_algo = 0;
- opt.compress_algo = -1;
- opt.s2k_mode = 3; /* iterated+salted */
- opt.s2k_digest_algo = DIGEST_ALGO_SHA256;
- opt.s2k_cipher_algo = CIPHER_ALGO_AES256;
- break;
case oOpenPGP:
case oRFC4880:
/* This is effectively the same as RFC2440, but with
@@ -2264,7 +2237,6 @@ set_compliance_option (enum cmd_and_opt_values option)
opt.escape_from = 1;
opt.not_dash_escaped = 0;
opt.def_cipher_algo = 0;
- opt.def_aead_algo = 0;
opt.def_digest_algo = 0;
opt.cert_digest_algo = 0;
opt.compress_algo = -1;
@@ -2282,7 +2254,6 @@ set_compliance_option (enum cmd_and_opt_values option)
opt.escape_from = 0;
opt.not_dash_escaped = 0;
opt.def_cipher_algo = 0;
- opt.def_aead_algo = 0;
opt.def_digest_algo = 0;
opt.cert_digest_algo = 0;
opt.compress_algo = -1;
@@ -2295,13 +2266,11 @@ set_compliance_option (enum cmd_and_opt_values option)
case oPGP8: opt.compliance = CO_PGP8; break;
case oGnuPG:
opt.compliance = CO_GNUPG;
- opt.flags.rfc4880bis = 1;
break;
case oDE_VS:
set_compliance_option (oOpenPGP);
opt.compliance = CO_DE_VS;
- opt.def_aead_algo = 0;
/* We divert here from the backward compatible rfc4880 algos. */
opt.s2k_digest_algo = DIGEST_ALGO_SHA256;
opt.s2k_cipher_algo = CIPHER_ALGO_AES256;
@@ -2382,14 +2351,12 @@ main (int argc, char **argv)
const char *trustdb_name = NULL;
#endif /*!NO_TRUST_MODELS*/
char *def_cipher_string = NULL;
- char *def_aead_string = NULL;
char *def_digest_string = NULL;
char *compress_algo_string = NULL;
char *cert_digest_string = NULL;
char *s2k_cipher_string = NULL;
char *s2k_digest_string = NULL;
char *pers_cipher_list = NULL;
- char *pers_aead_list = NULL;
char *pers_digest_list = NULL;
char *pers_compress_list = NULL;
int eyes_only=0;
@@ -2455,7 +2422,6 @@ main (int argc, char **argv)
opt.bz2_compress_level = -1; /* defaults to standard compress level */
/* note: if you change these lines, look at oOpenPGP */
opt.def_cipher_algo = 0;
- opt.def_aead_algo = 0;
opt.def_digest_algo = 0;
opt.cert_digest_algo = 0;
opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */
@@ -2502,7 +2468,6 @@ main (int argc, char **argv)
opt.emit_version = 0;
opt.weak_digests = NULL;
opt.compliance = CO_GNUPG;
- opt.flags.rfc4880bis = 1;
/* Check special options given on the command line. */
orig_argc = argc;
@@ -2716,6 +2681,7 @@ main (int argc, char **argv)
case aQuickRevUid:
case aQuickSetExpire:
case aQuickSetPrimaryUid:
+ case aQuickUpdatePref:
case aExportOwnerTrust:
case aImportOwnerTrust:
case aRebuildKeydbCaches:
@@ -2861,6 +2827,15 @@ main (int argc, char **argv)
allow_large_chunks = 1;
break;
+ case oCompatibilityFlags:
+ if (parse_compatibility_flags (pargs.r.ret_str, &opt.compat_flags,
+ compatibility_flags))
+ {
+ pargs.r_opt = ARGPARSE_INVALID_ARG;
+ pargs.err = ARGPARSE_PRINT_ERROR;
+ }
+ break;
+
case oStatusFD:
set_status_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) );
break;
@@ -3031,7 +3006,6 @@ main (int argc, char **argv)
case oOpenPGP:
case oRFC2440:
case oRFC4880:
- case oRFC4880bis:
case oPGP7:
case oPGP8:
case oGnuPG:
@@ -3269,9 +3243,6 @@ main (int argc, char **argv)
case oCipherAlgo:
def_cipher_string = xstrdup(pargs.r.ret_str);
break;
- case oAEADAlgo:
- def_aead_string = xstrdup (pargs.r.ret_str);
- break;
case oDigestAlgo:
def_digest_string = xstrdup(pargs.r.ret_str);
break;
@@ -3388,6 +3359,11 @@ main (int argc, char **argv)
if (rc)
log_error (_("invalid filter option: %s\n"), gpg_strerror (rc));
break;
+ case oListFilter:
+ rc = parse_and_set_list_filter (pargs.r.ret_str);
+ if (rc)
+ log_error (_("invalid filter option: %s\n"), gpg_strerror (rc));
+ break;
case oListOptions:
if(!parse_list_options(pargs.r.ret_str))
{
@@ -3553,9 +3529,6 @@ main (int argc, char **argv)
case oPersonalCipherPreferences:
pers_cipher_list=pargs.r.ret_str;
break;
- case oPersonalAEADPreferences:
- pers_aead_list = pargs.r.ret_str;
- break;
case oPersonalDigestPreferences:
pers_digest_list=pargs.r.ret_str;
break;
@@ -3849,11 +3822,6 @@ main (int argc, char **argv)
if( may_coredump && !opt.quiet )
log_info(_("WARNING: program may create a core file!\n"));
- if (!opt.flags.rfc4880bis)
- {
- opt.mimemode = 0; /* This will use text mode instead. */
- }
-
if (eyes_only) {
if (opt.set_filename)
log_info(_("WARNING: %s overrides %s\n"),
@@ -3920,6 +3888,8 @@ main (int argc, char **argv)
}
set_debug (debug_level);
+ if (opt.verbose) /* Print the compatibility flags. */
+ parse_compatibility_flags (NULL, &opt.compat_flags, compatibility_flags);
gnupg_set_compliance_extra_info (opt.min_rsa_length);
if (DBG_CLOCK)
log_clock ("start");
@@ -3944,13 +3914,6 @@ main (int argc, char **argv)
if ( openpgp_cipher_test_algo (opt.def_cipher_algo) )
log_error(_("selected cipher algorithm is invalid\n"));
}
- if (def_aead_string)
- {
- opt.def_aead_algo = string_to_aead_algo (def_aead_string);
- xfree (def_aead_string); def_aead_string = NULL;
- if (openpgp_aead_test_algo (opt.def_aead_algo))
- log_error(_("selected AEAD algorithm is invalid\n"));
- }
if( def_digest_string ) {
opt.def_digest_algo = string_to_digest_algo (def_digest_string);
xfree(def_digest_string); def_digest_string = NULL;
@@ -4011,9 +3974,6 @@ main (int argc, char **argv)
keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM))
log_error(_("invalid personal cipher preferences\n"));
- if (pers_aead_list && keygen_set_std_prefs (pers_aead_list, PREFTYPE_AEAD))
- log_error(_("invalid personal AEAD preferences\n"));
-
if(pers_digest_list &&
keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH))
log_error(_("invalid personal digest preferences\n"));
@@ -4087,7 +4047,7 @@ main (int argc, char **argv)
/* Check our chosen algorithms against the list of legal
algorithms. */
- if(!GNUPG && !opt.flags.rfc4880bis)
+ if(!GNUPG)
{
const char *badalg=NULL;
preftype_t badtype=PREFTYPE_NONE;
@@ -4098,12 +4058,6 @@ main (int argc, char **argv)
badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
badtype = PREFTYPE_SYM;
}
- else if(opt.def_aead_algo
- && !algo_available(PREFTYPE_AEAD, opt.def_aead_algo, NULL))
- {
- badalg = openpgp_aead_algo_name (opt.def_aead_algo);
- badtype = PREFTYPE_AEAD;
- }
else if(opt.def_digest_algo
&& !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL))
{
@@ -4133,12 +4087,6 @@ main (int argc, char **argv)
badalg,
gnupg_compliance_option_string (opt.compliance));
break;
- case PREFTYPE_AEAD:
- log_info (_("AEAD algorithm '%s'"
- " may not be used in %s mode\n"),
- badalg,
- gnupg_compliance_option_string (opt.compliance));
- break;
case PREFTYPE_HASH:
log_info (_("digest algorithm '%s'"
" may not be used in %s mode\n"),
@@ -4164,7 +4112,6 @@ main (int argc, char **argv)
* is not. This is us being nice to the user informing her early
* that the chosen algorithms are not available. We also check
* and enforce this right before the actual operation. */
- /* FIXME: We also need to check the AEAD algo. */
if (opt.def_cipher_algo
&& ! gnupg_cipher_is_allowed (opt.compliance,
cmd == aEncr
@@ -4343,6 +4290,7 @@ main (int argc, char **argv)
case aQuickAddKey:
case aQuickRevUid:
case aQuickSetPrimaryUid:
+ case aQuickUpdatePref:
case aFullKeygen:
case aKeygen:
case aImport:
@@ -4843,6 +4791,14 @@ main (int argc, char **argv)
}
break;
+ case aQuickUpdatePref:
+ {
+ if (argc != 1)
+ wrong_args ("--quick-update-pref USER-ID");
+ keyedit_quick_update_pref (ctrl, *argv);
+ }
+ break;
+
case aFastImport:
opt.import_options |= IMPORT_FAST; /* fall through */
case aImport:
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 3bb99dc..ceded4a 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -812,3 +812,11 @@ get_revocation_reason (PKT_signature *sig, char **r_reason,
*r_comment = NULL;
return 0;
}
+
+const char *
+impex_filter_getval (void *cookie, const char *propname)
+{
+ (void)cookie;
+ (void)propname;
+ return NULL;
+}
diff --git a/g10/import.c b/g10/import.c
index bb0bf67..9fab46c 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -126,7 +126,8 @@ static int import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
static int chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
int *non_self);
static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock,
- u32 *keyid, unsigned int options);
+ u32 *keyid, unsigned int options,
+ kbnode_t *r_otherrevsigs);
static int any_uid_left (kbnode_t keyblock);
static void remove_all_non_self_sigs (kbnode_t *keyblock, u32 *keyid);
static int merge_blocks (ctrl_t ctrl, unsigned int options,
@@ -438,7 +439,7 @@ read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname,
goto leave;
}
- if (!delete_inv_parts (ctrl, keyblock, keyid, 0) )
+ if (!delete_inv_parts (ctrl, keyblock, keyid, 0, NULL) )
{
err = gpg_error (GPG_ERR_NO_USER_ID);
goto leave;
@@ -1429,7 +1430,8 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
}
-/* Helper for apply_*_filter in import.c and export.c. */
+/* Helper for apply_*_filter in import.c and export.c and also used by
+ * keylist.c. */
const char *
impex_filter_getval (void *cookie, const char *propname)
{
@@ -1439,11 +1441,32 @@ impex_filter_getval (void *cookie, const char *propname)
kbnode_t node = parm->node;
static char numbuf[20];
const char *result;
+ const char *s;
+ enum { scpNone = 0, scpPub, scpSub, scpUid, scpSig} scope = 0;
log_assert (ctrl && ctrl->magic == SERVER_CONTROL_MAGIC);
- if (node->pkt->pkttype == PKT_USER_ID
- || node->pkt->pkttype == PKT_ATTRIBUTE)
+ /* We allow a prefix delimited by a slash to limit the scope of the
+ * keyword. Note that "pub" also includes "sec" and "sub" includes
+ * "ssb". */
+ if ((s=strchr (propname, '/')) && s != propname)
+ {
+ size_t n = s - propname;
+ if (!strncmp (propname, "pub", n))
+ scope = scpPub;
+ else if (!strncmp (propname, "sub", n))
+ scope = scpSub;
+ else if (!strncmp (propname, "uid", n))
+ scope = scpUid;
+ else if (!strncmp (propname, "sig", n))
+ scope = scpSig;
+
+ propname = s + 1;
+ }
+
+ if ((node->pkt->pkttype == PKT_USER_ID
+ || node->pkt->pkttype == PKT_ATTRIBUTE)
+ && (!scope || scope == scpUid))
{
PKT_user_id *uid = node->pkt->pkt.user_id;
@@ -1472,7 +1495,8 @@ impex_filter_getval (void *cookie, const char *propname)
else
result = NULL;
}
- else if (node->pkt->pkttype == PKT_SIGNATURE)
+ else if (node->pkt->pkttype == PKT_SIGNATURE
+ && (!scope || scope == scpSig))
{
PKT_signature *sig = node->pkt->pkt.signature;
@@ -1502,10 +1526,12 @@ impex_filter_getval (void *cookie, const char *propname)
else
result = NULL;
}
- else if (node->pkt->pkttype == PKT_PUBLIC_KEY
- || node->pkt->pkttype == PKT_SECRET_KEY
- || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ else if (((node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_SECRET_KEY)
+ && (!scope || scope == scpPub))
+ || ((node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ && (!scope || scope == scpSub)))
{
PKT_public_key *pk = node->pkt->pkt.public_key;
@@ -1519,6 +1545,16 @@ impex_filter_getval (void *cookie, const char *propname)
snprintf (numbuf, sizeof numbuf, "%d", pk->pubkey_algo);
result = numbuf;
}
+ else if (!strcmp (propname, "key_size"))
+ {
+ snprintf (numbuf, sizeof numbuf, "%u", nbits_from_pk (pk));
+ result = numbuf;
+ }
+ else if (!strcmp (propname, "algostr"))
+ {
+ pubkey_string (pk, parm->hexfpr, sizeof parm->hexfpr);
+ result = parm->hexfpr;
+ }
else if (!strcmp (propname, "key_created"))
{
snprintf (numbuf, sizeof numbuf, "%lu", (ulong)pk->timestamp);
@@ -1555,6 +1591,26 @@ impex_filter_getval (void *cookie, const char *propname)
hexfingerprint (pk, parm->hexfpr, sizeof parm->hexfpr);
result = parm->hexfpr;
}
+ else if (!strcmp (propname, "origin"))
+ {
+ result = key_origin_string (pk->keyorg);
+ }
+ else if (!strcmp (propname, "lastupd"))
+ {
+ snprintf (numbuf, sizeof numbuf, "%lu", (ulong)pk->keyupdate);
+ result = numbuf;
+ }
+ else if (!strcmp (propname, "url"))
+ {
+ if (pk->updateurl && *pk->updateurl)
+ {
+ /* Fixme: This might get truncated. */
+ mem2str (parm->hexfpr, pk->updateurl, sizeof parm->hexfpr);
+ result = parm->hexfpr;
+ }
+ else
+ result = "";
+ }
else
result = NULL;
}
@@ -1871,8 +1927,9 @@ update_key_origin (kbnode_t keyblock, u32 curtime, int origin, const char *url)
* even most error messages are suppressed. ORIGIN is the origin of
* the key (0 for unknown) and URL the corresponding URL. FROM_SK
* indicates that the key has been made from a secret key. If R_SAVED
- * is not NULL a boolean will be stored indicating whether the keyblock
- * has valid parts.
+ * is not NULL a boolean will be stored indicating whether the
+ * keyblock has valid parts. Unless OTHERREVSIGS is NULL it is
+ * updated with encountered new revocation signatures.
*/
static gpg_error_t
import_one_real (ctrl_t ctrl,
@@ -1880,7 +1937,8 @@ import_one_real (ctrl_t ctrl,
unsigned char **fpr, size_t *fpr_len, unsigned int options,
int from_sk, int silent,
import_screener_t screener, void *screener_arg,
- int origin, const char *url, int *r_valid)
+ int origin, const char *url, int *r_valid,
+ kbnode_t *otherrevsigs)
{
gpg_error_t err = 0;
PKT_public_key *pk;
@@ -2021,7 +2079,7 @@ import_one_real (ctrl_t ctrl,
}
/* Delete invalid parts and bail out if there are no user ids left. */
- if (!delete_inv_parts (ctrl, keyblock, keyid, options))
+ if (!delete_inv_parts (ctrl, keyblock, keyid, options, otherrevsigs))
{
if (!silent)
{
@@ -2413,10 +2471,12 @@ import_one (ctrl_t ctrl,
int origin, const char *url, int *r_valid)
{
gpg_error_t err;
+ kbnode_t otherrevsigs = NULL;
+ kbnode_t node;
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
from_sk, silent, screener, screener_arg,
- origin, url, r_valid);
+ origin, url, r_valid, &otherrevsigs);
if (gpg_err_code (err) == GPG_ERR_TOO_LARGE
&& gpg_err_source (err) == GPG_ERR_SOURCE_KEYBOX
&& ((options & (IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN))
@@ -2432,8 +2492,17 @@ import_one (ctrl_t ctrl,
options |= IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN;
err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options,
from_sk, silent, screener, screener_arg,
- origin, url, r_valid);
+ origin, url, r_valid, &otherrevsigs);
+ }
+
+ /* Finally try to import other revocation certificates. For example
+ * those of a former key appended to the current key. */
+ if (!err)
+ {
+ for (node = otherrevsigs; node; node = node->next)
+ import_revoke_cert (ctrl, node, options, stats);
}
+ release_kbnode (otherrevsigs);
return err;
}
@@ -3422,9 +3491,8 @@ list_standalone_revocation (ctrl_t ctrl, PKT_signature *sig, int sigrc)
}
-/****************
- * Import a revocation certificate; this is a single signature packet.
- */
+/* Import a revocation certificate; only the first packet in the
+ * NODE-list is considered. */
static int
import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
struct import_stats_s *stats)
@@ -3441,10 +3509,12 @@ import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options,
/* No error output for --show-keys. */
silent = (options & (IMPORT_SHOW | IMPORT_DRY_RUN));
- log_assert (!node->next );
log_assert (node->pkt->pkttype == PKT_SIGNATURE );
log_assert (IS_KEY_REV (node->pkt->pkt.signature));
+ /* FIXME: We can do better here by using the issuer fingerprint if
+ * available. We should also make use of get_keyblock_byfprint_fast. */
+
keyid[0] = node->pkt->pkt.signature->keyid[0];
keyid[1] = node->pkt->pkt.signature->keyid[1];
@@ -3788,12 +3858,15 @@ chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, int *non_self)
/* Delete all parts which are invalid and those signatures whose
* public key algorithm is not available in this implementation; but
* consider RSA as valid, because parse/build_packets knows about it.
+ * If R_OTHERREVSIGS is not NULL, it is used to return a list of
+ * revocation certificates which have been deleted from KEYBLOCK but
+ * should be handled later.
*
* Returns: True if at least one valid user-id is left over.
*/
static int
delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
- unsigned int options)
+ unsigned int options, kbnode_t *r_otherrevsigs)
{
kbnode_t node;
int nvalid=0, uid_seen=0, subkey_seen=0;
@@ -3883,6 +3956,16 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
if(opt.verbose)
log_info( _("key %s: revocation certificate"
" at wrong place - skipped\n"),keystr(keyid));
+ if (r_otherrevsigs)
+ {
+ PACKET *pkt;
+
+ pkt = xcalloc (1, sizeof *pkt);
+ pkt->pkttype = PKT_SIGNATURE;
+ pkt->pkt.signature = copy_signature
+ (NULL, node->pkt->pkt.signature);
+ *r_otherrevsigs = new_kbnode2 (*r_otherrevsigs, pkt);
+ }
delete_kbnode( node );
}
else
@@ -3905,6 +3988,16 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
delete_kbnode( node );
}
}
+ else if (r_otherrevsigs)
+ {
+ PACKET *pkt;
+
+ pkt = xcalloc (1, sizeof *pkt);
+ pkt->pkttype = PKT_SIGNATURE;
+ pkt->pkt.signature = copy_signature
+ (NULL, node->pkt->pkt.signature);
+ *r_otherrevsigs = new_kbnode2 (*r_otherrevsigs, pkt);
+ }
}
}
else if (node->pkt->pkttype == PKT_SIGNATURE
diff --git a/g10/kbnode.c b/g10/kbnode.c
index 93035e8..1f2328d 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -98,6 +98,19 @@ new_kbnode( PACKET *pkt )
}
+/* Same as new_kbnode but insert the new node in front of LIST. Returns
+ * the new list. */
+kbnode_t
+new_kbnode2 (kbnode_t list, PACKET *pkt)
+{
+ kbnode_t n;
+
+ n = new_kbnode (pkt);
+ n->next = list;
+ return n;
+}
+
+
KBNODE
clone_kbnode( KBNODE node )
{
diff --git a/g10/keydb.h b/g10/keydb.h
index a91309a..771bc8e 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -569,6 +569,7 @@ gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );
+kbnode_t new_kbnode2 (kbnode_t list, PACKET *pkt);
KBNODE clone_kbnode( KBNODE node );
void release_kbnode( KBNODE n );
void delete_kbnode( KBNODE node );
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 0453801..83c20b8 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1,7 +1,7 @@
/* keyedit.c - Edit properties of a key
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
* Copyright (C) 1998-2017 Werner Koch
- * Copyright (C) 2015, 2016 g10 Code GmbH
+ * Copyright (C) 2015, 2016, 2022 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -78,7 +78,8 @@ static gpg_error_t menu_expire (ctrl_t ctrl, kbnode_t pub_keyblock,
static int menu_changeusage (ctrl_t ctrl, kbnode_t keyblock);
static int menu_backsign (ctrl_t ctrl, kbnode_t pub_keyblock);
static int menu_set_primary_uid (ctrl_t ctrl, kbnode_t pub_keyblock);
-static int menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock);
+static int menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock,
+ int unattended);
static int menu_set_keyserver_url (ctrl_t ctrl,
const char *url, kbnode_t pub_keyblock);
static int menu_set_notation (ctrl_t ctrl,
@@ -2157,7 +2158,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
" for the selected user IDs? (y/N) ")
: _("Really update the preferences? (y/N) ")))
{
- if (menu_set_preferences (ctrl, keyblock))
+ if (menu_set_preferences (ctrl, keyblock, 0))
{
merge_keys_and_selfsig (ctrl, keyblock);
modified = 1;
@@ -2654,6 +2655,45 @@ keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
}
+/* Unattended updating of the preference tro the standard preferences.
+ * USERNAME specifies the key. This is basically the same as
+ * gpg --edit-key <<userif> updpref save
+ */
+void
+keyedit_quick_update_pref (ctrl_t ctrl, const char *username)
+{
+ gpg_error_t err;
+ KEYDB_HANDLE kdbhd = NULL;
+ kbnode_t keyblock = NULL;
+
+#ifdef HAVE_W32_SYSTEM
+ /* See keyedit_menu for why we need this. */
+ check_trustdb_stale (ctrl);
+#endif
+
+ err = quick_find_keyblock (ctrl, username, 1, &kdbhd, &keyblock);
+ if (err)
+ goto leave;
+
+ if (menu_set_preferences (ctrl, keyblock, 1))
+ {
+ merge_keys_and_selfsig (ctrl, keyblock);
+ err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
+ if (err)
+ {
+ log_error (_("update failed: %s\n"), gpg_strerror (err));
+ goto leave;
+ }
+ }
+
+ leave:
+ if (err)
+ write_status_error ("keyedit.updpref", err);
+ release_kbnode (keyblock);
+ keydb_release (kdbhd);
+}
+
+
/* Find a keyblock by fingerprint because only this uniquely
* identifies a key and may thus be used to select a key for
* unattended subkey creation os key signing. */
@@ -3353,145 +3393,12 @@ tty_print_notations (int indent, PKT_signature * sig)
static void
show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
{
- const prefitem_t fake = { 0, 0 };
- const prefitem_t *prefs;
- int i;
-
if (!uid)
return;
- if (uid->prefs)
- prefs = uid->prefs;
- else if (verbose)
- prefs = &fake;
- else
- return;
-
if (verbose)
{
- int any, des_seen = 0, sha1_seen = 0, uncomp_seen = 0;
-
- tty_printf (" ");
- tty_printf (_("Cipher: "));
- for (i = any = 0; prefs[i].type; i++)
- {
- if (prefs[i].type == PREFTYPE_SYM)
- {
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (!openpgp_cipher_test_algo (prefs[i].value)
- && prefs[i].value < 100)
- tty_printf ("%s", openpgp_cipher_algo_name (prefs[i].value));
- else
- tty_printf ("[%d]", prefs[i].value);
- if (prefs[i].value == CIPHER_ALGO_3DES)
- des_seen = 1;
- }
- }
- if (!des_seen)
- {
- if (any)
- tty_printf (", ");
- tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
- }
- tty_printf ("\n ");
- tty_printf (_("AEAD: "));
- for (i = any = 0; prefs[i].type; i++)
- {
- if (prefs[i].type == PREFTYPE_AEAD)
- {
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (!openpgp_aead_test_algo (prefs[i].value)
- && prefs[i].value < 100)
- tty_printf ("%s", openpgp_aead_algo_name (prefs[i].value));
- else
- tty_printf ("[%d]", prefs[i].value);
- }
- }
- tty_printf ("\n ");
- tty_printf (_("Digest: "));
- for (i = any = 0; prefs[i].type; i++)
- {
- if (prefs[i].type == PREFTYPE_HASH)
- {
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (!gcry_md_test_algo (prefs[i].value) && prefs[i].value < 100)
- tty_printf ("%s", gcry_md_algo_name (prefs[i].value));
- else
- tty_printf ("[%d]", prefs[i].value);
- if (prefs[i].value == DIGEST_ALGO_SHA1)
- sha1_seen = 1;
- }
- }
- if (!sha1_seen)
- {
- if (any)
- tty_printf (", ");
- tty_printf ("%s", gcry_md_algo_name (DIGEST_ALGO_SHA1));
- }
- tty_printf ("\n ");
- tty_printf (_("Compression: "));
- for (i = any = 0; prefs[i].type; i++)
- {
- if (prefs[i].type == PREFTYPE_ZIP)
- {
- const char *s = compress_algo_to_string (prefs[i].value);
-
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (s && prefs[i].value < 100)
- tty_printf ("%s", s);
- else
- tty_printf ("[%d]", prefs[i].value);
- if (prefs[i].value == COMPRESS_ALGO_NONE)
- uncomp_seen = 1;
- }
- }
- if (!uncomp_seen)
- {
- if (any)
- tty_printf (", ");
- else
- {
- tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_ZIP));
- tty_printf (", ");
- }
- tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
- }
- if (uid->flags.mdc || uid->flags.aead || !uid->flags.ks_modify)
- {
- tty_printf ("\n ");
- tty_printf (_("Features: "));
- any = 0;
- if (uid->flags.mdc)
- {
- tty_printf ("MDC");
- any = 1;
- }
- if (uid->flags.aead)
- {
- if (any)
- tty_printf (", ");
- tty_printf ("AEAD");
- }
- if (!uid->flags.ks_modify)
- {
- if (any)
- tty_printf (", ");
- tty_printf (_("Keyserver no-modify"));
- }
- }
- tty_printf ("\n");
+ show_preferences (uid, 4, -1, 1);
if (selfsig)
{
@@ -3518,22 +3425,7 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
}
else
{
- tty_printf (" ");
- for (i = 0; prefs[i].type; i++)
- {
- tty_printf (" %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
- prefs[i].type == PREFTYPE_AEAD ? 'A' :
- prefs[i].type == PREFTYPE_HASH ? 'H' :
- prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
- prefs[i].value);
- }
- if (uid->flags.mdc)
- tty_printf (" [mdc]");
- if (uid->flags.aead)
- tty_printf (" [aead]");
- if (!uid->flags.ks_modify)
- tty_printf (" [no-ks-modify]");
- tty_printf ("\n");
+ show_preferences (uid, 4, -1, 0);
}
}
@@ -5260,10 +5152,11 @@ menu_set_primary_uid (ctrl_t ctrl, kbnode_t pub_keyblock)
/*
- * Set preferences to new values for the selected user IDs
+ * Set preferences to new values for the selected user IDs.
+ * --quick-update-pred calls this with UNATTENDED set.
*/
static int
-menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock)
+menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock, int unattended)
{
PKT_public_key *main_pk;
PKT_user_id *uid;
@@ -5272,9 +5165,10 @@ menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock)
int selected, select_all;
int modified = 0;
- no_primary_warning (pub_keyblock);
+ if (!unattended)
+ no_primary_warning (pub_keyblock);
- select_all = !count_selected_uids (pub_keyblock);
+ select_all = unattended? 1 : !count_selected_uids (pub_keyblock);
/* Now we can actually change the self signature(s) */
main_pk = NULL;
diff --git a/g10/keyedit.h b/g10/keyedit.h
index b6e5b58..ea4fd25 100644
--- a/g10/keyedit.h
+++ b/g10/keyedit.h
@@ -55,6 +55,7 @@ void keyedit_quick_set_expire (ctrl_t ctrl,
char **subkeyfprs);
void keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
const char *primaryuid);
+void keyedit_quick_update_pref (ctrl_t ctrl, const char *username);
void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock, int print_sec);
int keyedit_print_one_sig (ctrl_t ctrl, estream_t fp,
int rc, kbnode_t keyblock,
diff --git a/g10/keygen.c b/g10/keygen.c
index 7a79b37..4dcf7a4 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -407,7 +407,7 @@ keygen_set_std_prefs (const char *string,int personal)
strcat(dummy_string,"S7 ");
strcat(dummy_string,"S2 "); /* 3DES */
- if (opt.flags.rfc4880bis && !openpgp_aead_test_algo (AEAD_ALGO_OCB))
+ if (!openpgp_aead_test_algo (AEAD_ALGO_OCB))
strcat(dummy_string,"A2 ");
if (personal)
@@ -564,29 +564,6 @@ keygen_set_std_prefs (const char *string,int personal)
opt.personal_cipher_prefs[i].value = 0;
}
}
- else if (personal == PREFTYPE_AEAD)
- {
- xfree(opt.personal_aead_prefs);
-
- if (!naead)
- opt.personal_aead_prefs = NULL;
- else
- {
- int i;
-
- opt.personal_aead_prefs=
- xmalloc(sizeof(prefitem_t *)*(naead+1));
-
- for (i=0; i<naead; i++)
- {
- opt.personal_aead_prefs[i].type = PREFTYPE_AEAD;
- opt.personal_aead_prefs[i].value = aead[i];
- }
-
- opt.personal_aead_prefs[i].type = PREFTYPE_NONE;
- opt.personal_aead_prefs[i].value = 0;
- }
- }
else if(personal==PREFTYPE_HASH)
{
xfree(opt.personal_digest_prefs);
@@ -915,7 +892,7 @@ keygen_upd_std_prefs (PKT_signature *sig, void *opaque)
/* Make sure that the MDC feature flag is set if needed. */
add_feature_mdc (sig,mdc_available);
add_feature_aead (sig, aead_available);
- add_feature_v5 (sig, opt.flags.rfc4880bis);
+ add_feature_v5 (sig, 1);
add_keyserver_modify (sig,ks_modify);
keygen_add_keyserver_url(sig,NULL);
@@ -3410,10 +3387,7 @@ parse_key_parameter_part (ctrl_t ctrl,
}
}
else if (!ascii_strcasecmp (s, "v5"))
- {
- if (opt.flags.rfc4880bis)
- keyversion = 5;
- }
+ keyversion = 5;
else if (!ascii_strcasecmp (s, "v4"))
keyversion = 4;
else
@@ -3672,7 +3646,7 @@ parse_key_parameter_part (ctrl_t ctrl,
* ecdsa := Use algorithm ECDSA.
* eddsa := Use algorithm EdDSA.
* ecdh := Use algorithm ECDH.
- * v5 := Create version 5 key (requires option --rfc4880bis)
+ * v5 := Create version 5 key
*
* There are several defaults and fallbacks depending on the
* algorithm. PART can be used to select which part of STRING is
@@ -4454,9 +4428,9 @@ read_parameter_file (ctrl_t ctrl, const char *fname )
}
}
- if (!opt.flags.rfc4880bis && (keywords[i].key == pVERSION
- || keywords[i].key == pSUBVERSION))
- ; /* Ignore version unless --rfc4880bis is active. */
+ if ((keywords[i].key == pVERSION
+ || keywords[i].key == pSUBVERSION))
+ ; /* Ignore version. */
else
{
r = xmalloc_clear( sizeof *r + strlen( value ) );
@@ -4551,14 +4525,11 @@ quickgen_set_para (struct para_data_s *para, int for_subkey,
para = r;
}
- if (opt.flags.rfc4880bis)
- {
- r = xmalloc_clear (sizeof *r + 20);
- r->key = for_subkey? pSUBVERSION : pVERSION;
- snprintf (r->u.value, 20, "%d", version);
- r->next = para;
- para = r;
- }
+ r = xmalloc_clear (sizeof *r + 20);
+ r->key = for_subkey? pSUBVERSION : pVERSION;
+ snprintf (r->u.value, 20, "%d", version);
+ r->next = para;
+ para = r;
if (keytime)
{
@@ -5315,8 +5286,8 @@ card_store_key_with_backup (ctrl_t ctrl, PKT_public_key *sub_psk,
goto leave;
}
- err = receive_seckey_from_agent (ctrl, cipherhd, 0,
- &cache_nonce, hexgrip, sk);
+ err = receive_seckey_from_agent (ctrl, cipherhd, 0, 0,
+ &cache_nonce, hexgrip, sk, NULL);
if (err)
{
log_error ("error getting secret key from agent: %s\n",
diff --git a/g10/keylist.c b/g10/keylist.c
index e785aa0..1ced732 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -44,6 +44,8 @@
#include "../common/mbox-util.h"
#include "../common/zb32.h"
#include "tofu.h"
+#include "../common/init.h"
+#include "../common/recsel.h"
#include "../common/compliance.h"
#include "../common/pkscreening.h"
@@ -64,16 +66,26 @@ struct keylist_context
int no_validity; /* Do not show validity. */
};
-
-static void list_keyblock (ctrl_t ctrl,
- kbnode_t keyblock, int secret, int has_secret,
- int fpr, struct keylist_context *listctx);
+/* An object and a global instance to store selectors created from
+ * --list-filter select=EXPR.
+ */
+struct list_filter_s
+{
+ recsel_expr_t selkey;
+};
+struct list_filter_s list_filter;
/* The stream used to write attribute packets to. */
static estream_t attrib_fp;
+
+
+static void list_keyblock (ctrl_t ctrl,
+ kbnode_t keyblock, int secret, int has_secret,
+ int fpr, struct keylist_context *listctx);
+
/* Release resources from a keylist context. */
static void
keylist_context_release (struct keylist_context *listctx)
@@ -82,6 +94,49 @@ keylist_context_release (struct keylist_context *listctx)
}
+static void
+release_list_filter (struct list_filter_s *filt)
+{
+ recsel_release (filt->selkey);
+ filt->selkey = NULL;
+}
+
+
+static void
+cleanup_keylist_globals (void)
+{
+ release_list_filter (&list_filter);
+}
+
+
+/* Parse and set an list filter from string. STRING has the format
+ * "NAME=EXPR" with NAME being the name of the filter. Spaces before
+ * and after NAME are not allowed. If this function is all called
+ * several times all expressions for the same NAME are concatenated.
+ * Supported filter names are:
+ *
+ * - select :: If the expression evaluates to true for a certain key
+ * this key will be listed. The expression may use any
+ * variable defined for the export and import filters.
+ *
+ */
+gpg_error_t
+parse_and_set_list_filter (const char *string)
+{
+ gpg_error_t err;
+
+ /* Auto register the cleanup function. */
+ register_mem_cleanup_func (cleanup_keylist_globals);
+
+ if (!strncmp (string, "select=", 7))
+ err = recsel_parse_expr (&list_filter.selkey, string+7);
+ else
+ err = gpg_error (GPG_ERR_INV_NAME);
+
+ return err;
+}
+
+
/* List the keys. If list is NULL, all available keys are listed.
* With LOCATE_MODE set the locate algorithm is used to find a key; if
* in addition NO_LOCAL is set the locate does not look into the local
@@ -306,6 +361,173 @@ print_card_key_info (estream_t fp, kbnode_t keyblock)
#endif /*ENABLE_CARD_SUPPORT*/
+/* Print the preferences line. Allowed values for MODE are:
+ * -1 - print to the TTY
+ * 0 - print to stdout.
+ * 1 - use log_info
+ */
+void
+show_preferences (PKT_user_id *uid, int indent, int mode, int verbose)
+{
+ estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
+ const prefitem_t fake = { 0, 0 };
+ const prefitem_t *prefs;
+ int i;
+
+ if (!uid)
+ return;
+
+ if (uid->prefs)
+ prefs = uid->prefs;
+ else if (verbose)
+ prefs = &fake;
+ else
+ return;
+
+ if (verbose)
+ {
+ int any, des_seen = 0, sha1_seen = 0, uncomp_seen = 0;
+
+ tty_fprintf (fp, "%*s %s", indent, "", _("Cipher: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_SYM)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!openpgp_cipher_test_algo (prefs[i].value)
+ && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", openpgp_cipher_algo_name (prefs[i].value));
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ if (prefs[i].value == CIPHER_ALGO_3DES)
+ des_seen = 1;
+ }
+ }
+ if (!des_seen)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, "%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
+ }
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("AEAD: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_AEAD)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!openpgp_aead_test_algo (prefs[i].value)
+ && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", openpgp_aead_algo_name (prefs[i].value));
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ }
+ }
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("Digest: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_HASH)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!gcry_md_test_algo (prefs[i].value) && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", gcry_md_algo_name (prefs[i].value));
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ if (prefs[i].value == DIGEST_ALGO_SHA1)
+ sha1_seen = 1;
+ }
+ }
+ if (!sha1_seen)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, "%s", gcry_md_algo_name (DIGEST_ALGO_SHA1));
+ }
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("Compression: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_ZIP)
+ {
+ const char *s = compress_algo_to_string (prefs[i].value);
+
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (s && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", s);
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ if (prefs[i].value == COMPRESS_ALGO_NONE)
+ uncomp_seen = 1;
+ }
+ }
+ if (!uncomp_seen)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ else
+ {
+ tty_fprintf (fp, "%s",
+ compress_algo_to_string (COMPRESS_ALGO_ZIP));
+ tty_fprintf (fp, ", ");
+ }
+ tty_fprintf (fp, "%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
+ }
+ if (uid->flags.mdc || uid->flags.aead || !uid->flags.ks_modify)
+ {
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("Features: "));
+ any = 0;
+ if (uid->flags.mdc)
+ {
+ tty_fprintf (fp, "MDC");
+ any = 1;
+ }
+ if (uid->flags.aead)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, "AEAD");
+ }
+ if (!uid->flags.ks_modify)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, _("Keyserver no-modify"));
+ }
+ }
+ tty_fprintf (fp, "\n");
+ }
+ else
+ {
+ tty_fprintf (fp, "%*s", indent, "");
+ for (i = 0; prefs[i].type; i++)
+ {
+ tty_fprintf (fp, " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
+ prefs[i].type == PREFTYPE_AEAD ? 'A' :
+ prefs[i].type == PREFTYPE_HASH ? 'H' :
+ prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
+ prefs[i].value);
+ }
+ if (uid->flags.mdc)
+ tty_fprintf (fp, " [mdc]");
+ if (uid->flags.aead)
+ tty_fprintf (fp, " [aead]");
+ if (!uid->flags.ks_modify)
+ tty_fprintf (fp, " [no-ks-modify]");
+ tty_fprintf (fp, "\n");
+ }
+}
+
+
/* Flags = 0x01 hashed 0x02 critical. */
static void
status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
@@ -1269,6 +1491,11 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
print_utf8_buffer (es_stdout, uid->name, uid->len);
es_putc ('\n', es_stdout);
+ if ((opt.list_options & LIST_SHOW_PREF_VERBOSE))
+ show_preferences (uid, indent+2, 0, 1);
+ else if ((opt.list_options & LIST_SHOW_PREF))
+ show_preferences (uid, indent+2, 0, 0);
+
if (opt.with_wkd_hash)
{
char *mbox, *hash, *p;
@@ -1991,6 +2218,7 @@ reorder_keyblock (KBNODE keyblock)
do_reorder_keyblock (keyblock, 0);
}
+
static void
list_keyblock (ctrl_t ctrl,
KBNODE keyblock, int secret, int has_secret, int fpr,
@@ -1998,6 +2226,24 @@ list_keyblock (ctrl_t ctrl,
{
reorder_keyblock (keyblock);
+ if (list_filter.selkey)
+ {
+ int selected = 0;
+ struct impex_filter_parm_s parm;
+ parm.ctrl = ctrl;
+
+ for (parm.node = keyblock; parm.node; parm.node = parm.node->next)
+ {
+ if (recsel_select (list_filter.selkey, impex_filter_getval, &parm))
+ {
+ selected = 1;
+ break;
+ }
+ }
+ if (!selected)
+ return; /* Skip this one. */
+ }
+
if (opt.with_colons)
list_keyblock_colon (ctrl, keyblock, secret, has_secret);
else if ((opt.list_options & LIST_SHOW_ONLY_FPR_MBOX))
diff --git a/g10/main.h b/g10/main.h
index 74c29cc..62d2651 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -41,8 +41,6 @@
# define DEFAULT_CIPHER_ALGO CIPHER_ALGO_3DES
#endif
-#define DEFAULT_AEAD_ALGO AEAD_ALGO_OCB
-
#define DEFAULT_DIGEST_ALGO ((GNUPG)? DIGEST_ALGO_SHA256:DIGEST_ALGO_SHA1)
#define DEFAULT_S2K_DIGEST_ALGO DIGEST_ALGO_SHA1
#ifdef HAVE_ZIP
@@ -169,7 +167,6 @@ const char *compress_algo_to_string(int algo);
int string_to_compress_algo(const char *string);
int check_compress_algo(int algo);
int default_cipher_algo(void);
-aead_algo_t default_aead_algo(void);
int default_compress_algo(void);
void compliance_failure(void);
@@ -240,8 +237,6 @@ void display_online_help( const char *keyword );
/*-- encode.c --*/
gpg_error_t setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
-gpg_error_t encrypt_seskey (DEK *dek, aead_algo_t aead_algo, DEK **r_seskey,
- void **r_enckey, size_t *r_enckeylen);
aead_algo_t use_aead (pk_list_t pk_list, int algo);
int use_mdc (pk_list_t pk_list,int algo);
int encrypt_symmetric (const char *filename );
@@ -436,10 +431,10 @@ gpg_error_t export_pubkey_buffer (ctrl_t ctrl, const char *keyspec,
void **r_data, size_t *r_datalen);
gpg_error_t receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
- int cleartext,
+ int cleartext, int mode1003,
char **cache_nonce_addr,
const char *hexgrip,
- PKT_public_key *pk);
+ PKT_public_key *pk, gcry_sexp_t *r_key);
gpg_error_t write_keyblock_to_output (kbnode_t keyblock,
int with_armor, unsigned int options);
@@ -469,6 +464,7 @@ void release_revocation_reason_info (struct revocation_reason_info *reason);
void public_key_list (ctrl_t ctrl, strlist_t list,
int locate_mode, int no_local);
void secret_key_list (ctrl_t ctrl, strlist_t list );
+gpg_error_t parse_and_set_list_filter (const char *string);
void print_subpackets_colon(PKT_signature *sig);
void reorder_keyblock (KBNODE keyblock);
void list_keyblock_direct (ctrl_t ctrl, kbnode_t keyblock, int secret,
@@ -477,6 +473,7 @@ int cmp_signodes (const void *av, const void *bv);
void print_fingerprint (ctrl_t ctrl, estream_t fp,
PKT_public_key *pk, int mode);
void print_revokers (estream_t fp, PKT_public_key *pk);
+void show_preferences (PKT_user_id *uid, int indent, int mode, int verbose);
void show_policy_url(PKT_signature *sig,int indent,int mode);
void show_keyserver_url(PKT_signature *sig,int indent,int mode);
void show_notation(PKT_signature *sig,int indent,int mode,int which);
diff --git a/g10/mainproc.c b/g10/mainproc.c
index f8f3c15..330ad10 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -726,7 +726,7 @@ proc_encrypted (CTX c, PACKET *pkt)
}
/* Compute compliance with CO_DE_VS. */
- if (!result && is_status_enabled ()
+ if (!result && (is_status_enabled () || opt.flags.require_compliance)
/* Overriding session key voids compliance. */
&& !opt.override_session_key
/* Check symmetric cipher. */
diff --git a/g10/misc.c b/g10/misc.c
index 5816012..dcf0018 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1387,17 +1387,6 @@ default_cipher_algo(void)
}
-aead_algo_t
-default_aead_algo(void)
-{
- if(opt.def_aead_algo)
- return opt.def_aead_algo;
- else if(opt.personal_aead_prefs)
- return opt.personal_aead_prefs[0].value;
- else
- return DEFAULT_AEAD_ALGO;
-}
-
/* There is no default_digest_algo function, but see
sign.c:hash_for() */
diff --git a/g10/options.h b/g10/options.h
index 10e61ea..c108626 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -92,7 +92,6 @@ struct
int no_armor;
int list_packets; /* Option --list-packets active. */
int def_cipher_algo;
- int def_aead_algo;
int force_mdc;
int disable_mdc;
int force_aead;
@@ -180,7 +179,6 @@ struct
const char *def_preference_list;
const char *def_keyserver_url;
prefitem_t *personal_cipher_prefs;
- prefitem_t *personal_aead_prefs;
prefitem_t *personal_digest_prefs;
prefitem_t *personal_compress_prefs;
struct weakhash *weak_digests;
@@ -308,6 +306,9 @@ struct
int no_symkey_cache; /* Disable the cache used for --symmetric. */
int use_keyboxd; /* Use the external keyboxd as storage backend. */
+
+ /* Compatibility flags (COMPAT_FLAG_xxxx). */
+ unsigned int compat_flags;
} opt;
/* CTRL is used to keep some global variables we currently can't
@@ -363,8 +364,11 @@ struct {
EXTERN_UNLESS_MAIN_MODULE int memory_debug_mode;
EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
+/* Compatibility flags */
+/* #define COMPAT_FOO 1 */
+
-/* Compatibility flags. */
+/* Compliance test macors. */
#define GNUPG (opt.compliance==CO_GNUPG || opt.compliance==CO_DE_VS)
#define RFC2440 (opt.compliance==CO_RFC2440)
#define RFC4880 (opt.compliance==CO_RFC4880)
@@ -402,6 +406,8 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define EXPORT_CLEAN (1<<5)
#define EXPORT_DANE_FORMAT (1<<7)
#define EXPORT_BACKUP (1<<10)
+#define EXPORT_REVOCS (1<<11)
+#define EXPORT_MODE1003 (1<<12)
#define LIST_SHOW_PHOTOS (1<<0)
#define LIST_SHOW_POLICY_URLS (1<<1)
@@ -418,6 +424,8 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define LIST_SHOW_USAGE (1<<11)
#define LIST_SHOW_ONLY_FPR_MBOX (1<<12)
#define LIST_SORT_SIGS (1<<13)
+#define LIST_SHOW_PREF (1<<14)
+#define LIST_SHOW_PREF_VERBOSE (1<<15)
#define VERIFY_SHOW_PHOTOS (1<<0)
#define VERIFY_SHOW_POLICY_URLS (1<<1)
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index b6aebbb..a033732 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -2752,11 +2752,15 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
break;
case 1001:
if (list_mode)
- es_fprintf (listfp, "\tgnu-dummy S2K");
+ es_fprintf (listfp, "\tgnu-dummy");
break;
case 1002:
if (list_mode)
- es_fprintf (listfp, "\tgnu-divert-to-card S2K");
+ es_fprintf (listfp, "\tgnu-divert-to-card");
+ break;
+ case 1003:
+ if (list_mode)
+ es_fprintf (listfp, "\tgnu-mode1003");
break;
default:
if (list_mode)
@@ -2768,7 +2772,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
}
/* Print some info. */
- if (list_mode)
+ if (list_mode && ski->s2k.mode != 1003)
{
es_fprintf (listfp, ", algo: %d,%s hash: %d",
ski->algo,
@@ -2779,8 +2783,9 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
es_fprintf (listfp, ", salt: ");
es_write_hexstring (listfp, ski->s2k.salt, 8, 0, NULL);
}
- es_putc ('\n', listfp);
- }
+ }
+ if (list_mode)
+ es_putc ('\n', listfp);
/* Read remaining protection parameters. */
if (ski->s2k.mode == 3)
@@ -2838,7 +2843,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
ski->ivlen = openpgp_cipher_blocklen (ski->algo);
log_assert (ski->ivlen <= sizeof (temp));
- if (ski->s2k.mode == 1001)
+ if (ski->s2k.mode == 1001 || ski->s2k.mode == 1003)
ski->ivlen = 0;
else if (ski->s2k.mode == 1002)
ski->ivlen = snlen < 16 ? snlen : 16;
@@ -2850,7 +2855,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
}
for (i = 0; i < ski->ivlen; i++, pktlen--)
temp[i] = iobuf_get_noeof (inp);
- if (list_mode)
+ if (list_mode && ski->s2k.mode != 1003)
{
es_fprintf (listfp,
ski->s2k.mode == 1002 ? "\tserial-number: "
@@ -2888,6 +2893,35 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
10 * 8);
pktlen = 0;
}
+ else if (ski->s2k.mode == 1003)
+ {
+ void *tmpp;
+
+ if (pktlen < 2) /* At least two bytes for parenthesis. */
+ {
+ err = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
+ }
+
+ tmpp = read_rest (inp, pktlen);
+ if (list_mode)
+ {
+ if (mpi_print_mode)
+ {
+ char *tmpsxp = canon_sexp_to_string (tmpp, pktlen);
+ es_fprintf (listfp, "\tskey[%d]: %s\n", npkey,
+ tmpsxp? trim_trailing_spaces (tmpsxp)
+ /* */: "[invalid S-expression]");
+ xfree (tmpsxp);
+ }
+ else
+ es_fprintf (listfp, "\tskey[%d]: [s-expression %lu octets]\n",
+ npkey, pktlen);
+ }
+ pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
+ tmpp, tmpp? pktlen * 8 : 0);
+ pktlen = 0;
+ }
else if (ski->is_protected)
{
void *tmpp;
diff --git a/g10/photoid.c b/g10/photoid.c
index 2c95930..72e6acf 100644
--- a/g10/photoid.c
+++ b/g10/photoid.c
@@ -36,7 +36,6 @@
#include "../common/util.h"
#include "packet.h"
#include "../common/status.h"
-#include "exec.h"
#include "keydb.h"
#include "../common/i18n.h"
#include "../common/iobuf.h"
@@ -46,6 +45,114 @@
#include "../common/ttyio.h"
#include "trustdb.h"
+#if defined (_WIN32)
+/* This is a nicer system() for windows that waits for programs to
+ return before returning control to the caller. I hate helpful
+ computers. */
+static int
+w32_system (const char *command)
+{
+ if (!strncmp (command, "!ShellExecute ", 14))
+ {
+ SHELLEXECUTEINFOW see;
+ wchar_t *wname;
+ int waitms;
+
+ command = command + 14;
+ while (spacep (command))
+ command++;
+ waitms = atoi (command);
+ if (waitms < 0)
+ waitms = 0;
+ else if (waitms > 60*1000)
+ waitms = 60000;
+ while (*command && !spacep (command))
+ command++;
+ while (spacep (command))
+ command++;
+
+ wname = utf8_to_wchar (command);
+ if (!wname)
+ return -1;
+
+ memset (&see, 0, sizeof see);
+ see.cbSize = sizeof see;
+ see.fMask = (SEE_MASK_NOCLOSEPROCESS
+ | SEE_MASK_NOASYNC
+ | SEE_MASK_FLAG_NO_UI
+ | SEE_MASK_NO_CONSOLE);
+ see.lpVerb = L"open";
+ see.lpFile = (LPCWSTR)wname;
+ see.nShow = SW_SHOW;
+
+ if (DBG_EXTPROG)
+ log_debug ("running ShellExecuteEx(open,'%s')\n", command);
+ if (!ShellExecuteExW (&see))
+ {
+ if (DBG_EXTPROG)
+ log_debug ("ShellExecuteEx failed: rc=%d\n", (int)GetLastError ());
+ xfree (wname);
+ return -1;
+ }
+ if (DBG_EXTPROG)
+ log_debug ("ShellExecuteEx succeeded (hProcess=%p,hInstApp=%d)\n",
+ see.hProcess, (int)see.hInstApp);
+
+ if (!see.hProcess)
+ {
+ gnupg_usleep (waitms*1000);
+ if (DBG_EXTPROG)
+ log_debug ("ShellExecuteEx ready (wait=%dms)\n", waitms);
+ }
+ else
+ {
+ WaitForSingleObject (see.hProcess, INFINITE);
+ if (DBG_EXTPROG)
+ log_debug ("ShellExecuteEx ready\n");
+ }
+ CloseHandle (see.hProcess);
+
+ xfree (wname);
+ }
+ else
+ {
+ char *string;
+ wchar_t *wstring;
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+
+ /* We must use a copy of the command as CreateProcess modifies
+ * this argument. */
+ string = xstrdup (command);
+ wstring = utf8_to_wchar (string);
+ xfree (string);
+ if (!wstring)
+ return -1;
+
+ memset (&pi, 0, sizeof(pi));
+ memset (&si, 0, sizeof(si));
+ si.cb = sizeof (si);
+
+ if (!CreateProcessW (NULL, wstring, NULL, NULL, FALSE,
+ DETACHED_PROCESS,
+ NULL, NULL, &si, &pi))
+ {
+ xfree (wstring);
+ return -1;
+ }
+
+ /* Wait for the child to exit */
+ WaitForSingleObject (pi.hProcess, INFINITE);
+
+ CloseHandle (pi.hProcess);
+ CloseHandle (pi.hThread);
+ xfree (wstring);
+ }
+
+ return 0;
+}
+#endif /*_W32*/
+
/* Generate a new photo id packet, or return NULL if canceled.
FIXME: Should we add a duplicates check similar to generate_user_id? */
PKT_user_id *
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 9b08cc4..459e759 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -1603,8 +1603,6 @@ select_algo_from_prefs(PK_LIST pk_list, int preftype,
prefs=NULL;
if(preftype==PREFTYPE_SYM && opt.personal_cipher_prefs)
prefs=opt.personal_cipher_prefs;
- else if(preftype==PREFTYPE_AEAD && opt.personal_aead_prefs)
- prefs=opt.personal_aead_prefs;
else if(preftype==PREFTYPE_HASH && opt.personal_digest_prefs)
prefs=opt.personal_digest_prefs;
else if(preftype==PREFTYPE_ZIP && opt.personal_compress_prefs)
@@ -1720,7 +1718,7 @@ select_aead_from_pklist (PK_LIST pk_list)
return 0; /* At least one recipient does not support it. */
}
- return default_aead_algo (); /* Yes, AEAD can be used. */
+ return AEAD_ALGO_OCB; /* Yes, AEAD can be used. */
}
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index cfe33b1..6ae0f4e 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -572,3 +572,11 @@ get_revocation_reason (PKT_signature *sig, char **r_reason,
*r_comment = NULL;
return 0;
}
+
+const char *
+impex_filter_getval (void *cookie, const char *propname)
+{
+ (void)cookie;
+ (void)propname;
+ return NULL;
+}
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 7e24864..051a534 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -1707,38 +1707,50 @@ sanitize_regexp(const char *old)
return new;
}
+
/* Used by validate_one_keyblock to confirm a regexp within a trust
- signature. Returns 1 for match, and 0 for no match or regex
- error. */
+ * signature. Returns 1 for match, and 0 for no match or regex
+ * error. */
static int
-check_regexp(const char *expr,const char *string)
+check_regexp (const char *expr,const char *string)
{
int ret;
char *regexp;
+ char *stringbuf = NULL;
+ regex_t pat;
- regexp=sanitize_regexp(expr);
-
- {
- regex_t pat;
+ regexp = sanitize_regexp (expr);
- ret=regcomp(&pat,regexp,REG_ICASE|REG_EXTENDED);
- if(ret==0)
- {
- ret=regexec(&pat,string,0,NULL,0);
- regfree(&pat);
- }
- ret=(ret==0);
- }
+ ret = regcomp (&pat, regexp, (REG_ICASE|REG_EXTENDED));
+ if (!ret)
+ {
+ if (*regexp == '<' && !strchr (string, '<')
+ && is_valid_mailbox (string))
+ {
+ /* The R.E. starts with an angle bracket but STRING seems to
+ * be a plain mailbox (e.g. "foo@example.org"). The
+ * commonly used R.E. pattern "<[^>]+[@.]example\.org>$"
+ * won't be able to detect this. Thus we enclose STRING
+ * into angle brackets for checking. */
+ stringbuf = xstrconcat ("<", string, ">", NULL);
+ string = stringbuf;
+ }
+ ret = regexec (&pat, string, 0, NULL, 0);
+ regfree (&pat);
+ }
- if(DBG_TRUST)
- log_debug("regexp '%s' ('%s') on '%s': %s\n",
- regexp,expr,string,ret?"YES":"NO");
+ ret = !ret;
- xfree(regexp);
+ if (DBG_TRUST)
+ log_debug ("regexp '%s' ('%s') on '%s'%s: %s\n",
+ regexp, expr, string, stringbuf? " (fixed)":"", ret? "YES":"NO");
+ xfree (regexp);
+ xfree (stringbuf);
return ret;
}
+
/*
* Return true if the key is signed by one of the keys in the given
* key ID list. User IDs with a valid signature are marked by node