summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2024-02-10 14:24:50 +0100
committerWerner Koch <wk@gnupg.org>2024-02-10 14:26:55 +0100
commit302afcb6f6af1dc88357acacfaa6829f0717b1c6 (patch)
treef198426cf8c1713df2c7f0ae6939fc9fad12667e
parentdoc: Suggest the use of a fingerprint for --default-key. (diff)
downloadgnupg2-302afcb6f6af1dc88357acacfaa6829f0717b1c6.tar.xz
gnupg2-302afcb6f6af1dc88357acacfaa6829f0717b1c6.zip
gpg: Add option --assert-pubkey_algo.
* g10/keyid.c (parse_one_algo_string): New. (compare_pubkey_string_part): New. (compare_pubkey_string): New. * g10/verify.c (check_assert_signer_list): New. * g10/mainproc.c (check_sig_and_print): Call check_assert_pubkey_algo. * g10/options.h (opt): Add field assert_pubkey_algos. * g10/gpg.c (oAssertPubkeyAlgo): New. (opts): Add "--assert-pubkey_algo". (assert_pubkey_algo_false): New. (main): Parse option. (g10_exit): Reorder RC modifications. Check assert_pubkey_algo_false. * common/status.h (ASSERT_PUBKEY_ALGOS): new. * common/t-support.h (LEAN_T_SUPPORT): Use a simplified version if this macro is set. * g10/gpgv.c (oAssertPubkeyAlgo): New. (opts): Add "--assert-pubkey_algo". (assert_pubkey_algo_false): New. (main): Parse option. (g10_exit): Check assert_pubkey_algo_false. * g10/t-keyid.c: New. * g10/Makefile.am: Add t-keyid. * g10/test-stubs.c: Add assert_pubkey_algos and assert_signer_list and remove from other tests. (check_assert_signer_list): Ditto. (check_assert_pubkey_algo): Ditto. -- GnuPG-bug-id: 6946
-rw-r--r--common/status.h1
-rw-r--r--common/t-support.h13
-rw-r--r--doc/DETAILS6
-rw-r--r--doc/gpg.texi23
-rw-r--r--doc/gpgv.texi5
-rw-r--r--g10/Makefile.am6
-rw-r--r--g10/gpg.c39
-rw-r--r--g10/gpgv.c32
-rw-r--r--g10/keydb.h1
-rw-r--r--g10/keyid.c124
-rw-r--r--g10/main.h2
-rw-r--r--g10/mainproc.c19
-rw-r--r--g10/options.h4
-rw-r--r--g10/t-keydb-get-keyblock.c9
-rw-r--r--g10/t-keydb.c10
-rw-r--r--g10/t-keyid.c129
-rw-r--r--g10/t-stutter.c9
-rw-r--r--g10/test-stubs.c18
-rw-r--r--g10/test.c1
-rw-r--r--g10/verify.c33
20 files changed, 425 insertions, 59 deletions
diff --git a/common/status.h b/common/status.h
index d249174d1..0a1266d3c 100644
--- a/common/status.h
+++ b/common/status.h
@@ -54,6 +54,7 @@ enum
STATUS_NEED_PASSPHRASE,
STATUS_VALIDSIG,
STATUS_ASSERT_SIGNER,
+ STATUS_ASSERT_PUBKEY_ALGO,
STATUS_SIG_ID,
STATUS_ENC_TO,
STATUS_NODATA,
diff --git a/common/t-support.h b/common/t-support.h
index 7aa46c00c..aa1b560fc 100644
--- a/common/t-support.h
+++ b/common/t-support.h
@@ -31,6 +31,8 @@
#ifndef GNUPG_COMMON_T_SUPPORT_H
#define GNUPG_COMMON_T_SUPPORT_H 1
+#ifndef LEAN_T_SUPPORT
+
#ifdef GCRYPT_VERSION
#error The regression tests should not include with gcrypt.h
#endif
@@ -45,11 +47,6 @@
# define getenv(a) (NULL)
#endif
-#ifndef DIM
-# define DIM(v) (sizeof(v)/sizeof((v)[0]))
-# define DIMof(type,member) DIM(((type *)0)->member)
-#endif
-
/* Replacement prototypes. */
void *gcry_xmalloc (size_t n);
@@ -65,6 +62,12 @@ void gcry_free (void *a);
#define xstrdup(a) gcry_xstrdup ( (a) )
#define xfree(a) gcry_free ( (a) )
+#endif /* LEAN_T_SUPPORT */
+
+#ifndef DIM
+# define DIM(v) (sizeof(v)/sizeof((v)[0]))
+# define DIMof(type,member) DIM(((type *)0)->member)
+#endif
/* Macros to print the result of a test. */
#define pass() do { ; } while(0)
diff --git a/doc/DETAILS b/doc/DETAILS
index fd95e511c..29e39708b 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -527,6 +527,12 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
--assert-signer is used. The fingerprint is printed with
uppercase hex digits.
+*** ASSERT_PUBKEY_ALGO <fingerprint> <state> <algostr>
+ This is emitted when option --assert-pubkey-algo is used and the
+ signing algorithms is accepted according to that list if state is
+ 1 or denied if state is 0. The fingerprint is printed with
+ uppercase hex digits.
+
*** SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
This is emitted only for signatures of class 0 or 1 which have
been verified okay. The string is a signature id and may be used
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 2f5b613d8..26e0ebdcd 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -1917,6 +1917,29 @@ is guaranteed to return with an exit code of 0 if and only if a
signature has been encountered, is valid, and the key matches one of
the fingerprints given by this option.
+@item --assert-pubkey-algo @var{algolist}
+@opindex assert-pubkey-algo
+During data signature verification this options checks whether the
+used public key algorithm matches the algorithms given by
+@var{algolist}. This option can be given multiple times to
+concatenate more algorithms to the list; the delimiter of the list are
+either commas or spaces.
+
+The algorithm names given in the list may either be verbatim names
+like "ed25519" with an optional leading single equal sign, or being
+prefixed with ">", ">=", "<=", or "<". That prefix operator is
+applied to the number part of the algorithm name; for example 2048 in
+"rsa2048" or 384 in "brainpoolP384r1". If the the leading non-digits
+in the name matches, the prefix operator is used to compare the number
+part, a trailing suffix is ignored in this case. For example an
+algorithm list ">rsa3000, >=brainpool384r1, =ed25519" allows RSA
+signatures with more that 3000 bits, Brainpool curves 384 and 512,
+and the ed25519 algorithm.
+
+With this option gpg (and also gpgv) is guaranteed to return with an
+exit code of 0 if and only if all valid signatures on data are made
+using a matching algorithm from the given list.
+
@item --auto-key-locate @var{mechanisms}
@itemx --no-auto-key-locate
diff --git a/doc/gpgv.texi b/doc/gpgv.texi
index 2dd9576b6..54ab23383 100644
--- a/doc/gpgv.texi
+++ b/doc/gpgv.texi
@@ -140,6 +140,10 @@ This option enables a mode in which filenames of the form
@file{-&n}, where n is a non-negative decimal number,
refer to the file descriptor n and not to a file with that name.
+@item --assert-pubkey-algo @var{algolist}
+@opindex assert-pubkey-algo
+This option works in the same way as described for @command{gpg}.
+
@end table
@mansect return value
@@ -190,4 +194,3 @@ The default keyring with the allowed keys.
@mansect see also
@command{gpg}(1)
@include see-also-note.texi
-
diff --git a/g10/Makefile.am b/g10/Makefile.am
index c5691f551..e8d8e9017 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -183,7 +183,7 @@ gpgv_LDFLAGS =
t_common_ldadd =
-module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter
+module_tests = t-rmd160 t-keydb t-keydb-get-keyblock t-stutter t-keyid
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)
@@ -200,6 +200,10 @@ t_stutter_SOURCES = t-stutter.c test-stubs.c \
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
$(LIBICONV) $(t_common_ldadd)
+t_keyid_SOURCES = t-keyid.c test-stubs.c $(common_source)
+t_keyid_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
+ $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
+ $(LIBICONV) $(t_common_ldadd)
$(PROGRAMS): $(needed_libs) ../common/libgpgrl.a
diff --git a/g10/gpg.c b/g10/gpg.c
index d4fbecdbe..1d0b9d09e 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -451,6 +451,7 @@ enum cmd_and_opt_values
oCompatibilityFlags,
oAddDesigRevoker,
oAssertSigner,
+ oAssertPubkeyAlgo,
oKbxBufferSize,
oNoop
@@ -715,6 +716,7 @@ static gpgrt_opt_t opts[] = {
#endif
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
ARGPARSE_s_s (oAssertSigner, "assert-signer", "@"),
+ ARGPARSE_s_s (oAssertPubkeyAlgo,"assert-pubkey-algo", "@"),
ARGPARSE_header ("Input", N_("Options controlling the input")),
@@ -1044,9 +1046,12 @@ static struct compatibility_flags_s compatibility_flags [] =
/* Can be set to true to force gpg to return with EXIT_FAILURE. */
int g10_errors_seen = 0;
-/* If opt.assert_signer_list is used and this variabale is not true
+/* If opt.assert_signer_list is used and this variable is not true
* gpg will be forced to return EXIT_FAILURE. */
int assert_signer_true = 0;
+/* If opt.assert_pubkey_algo is used and this variable is not true
+ * gpg will be forced to return EXIT_FAILURE. */
+int assert_pubkey_algo_false = 0;
static int utf8_strings =
@@ -3770,6 +3775,18 @@ main (int argc, char **argv)
add_to_strlist (&opt.assert_signer_list, pargs.r.ret_str);
break;
+ case oAssertPubkeyAlgo:
+ if (!opt.assert_pubkey_algos)
+ opt.assert_pubkey_algos = xstrdup (pargs.r.ret_str);
+ else
+ {
+ char *tmp = opt.assert_pubkey_algos;
+ opt.assert_pubkey_algos = xstrconcat (tmp, ",",
+ pargs.r.ret_str, NULL);
+ xfree (tmp);
+ }
+ break;
+
case oKbxBufferSize:
keybox_set_buffersize (pargs.r.ret_ulong, 0);
break;
@@ -5472,6 +5489,17 @@ emergency_cleanup (void)
void
g10_exit( int rc )
{
+ if (rc)
+ ;
+ else if (log_get_errorcount(0))
+ rc = 2;
+ else if (g10_errors_seen)
+ rc = 1;
+ else if (opt.assert_signer_list && !assert_signer_true)
+ rc = 1;
+ else if (opt.assert_pubkey_algos && assert_pubkey_algo_false)
+ rc = 1;
+
/* If we had an error but not printed an error message, do it now.
* Note that write_status_failure will never print a second failure
* status line. */
@@ -5496,15 +5524,6 @@ g10_exit( int rc )
gnupg_block_all_signals ();
emergency_cleanup ();
- if (rc)
- ;
- else if (log_get_errorcount(0))
- rc = 2;
- else if (g10_errors_seen)
- rc = 1;
- else if (opt.assert_signer_list && !assert_signer_true)
- rc = 1;
-
exit (rc);
}
diff --git a/g10/gpgv.c b/g10/gpgv.c
index f2895563e..c3b09f752 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -68,6 +68,7 @@ enum cmd_and_opt_values {
oWeakDigest,
oEnableSpecialFilenames,
oDebug,
+ oAssertPubkeyAlgo,
aTest
};
@@ -91,6 +92,7 @@ static gpgrt_opt_t opts[] = {
N_("|ALGO|reject signatures made with ALGO")),
ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"),
ARGPARSE_s_s (oDebug, "debug", "@"),
+ ARGPARSE_s_s (oAssertPubkeyAlgo,"assert-pubkey-algo", "@"),
ARGPARSE_end ()
};
@@ -119,6 +121,7 @@ static struct debug_flags_s debug_flags [] =
int g10_errors_seen = 0;
int assert_signer_true = 0;
+int assert_pubkey_algo_false = 0;
static char *
make_libversion (const char *libname, const char *(*getfnc)(const char*))
@@ -251,6 +254,19 @@ main( int argc, char **argv )
case oEnableSpecialFilenames:
enable_special_filenames ();
break;
+
+ case oAssertPubkeyAlgo:
+ if (!opt.assert_pubkey_algos)
+ opt.assert_pubkey_algos = xstrdup (pargs.r.ret_str);
+ else
+ {
+ char *tmp = opt.assert_pubkey_algos;
+ opt.assert_pubkey_algos = xstrconcat (tmp, ",",
+ pargs.r.ret_str, NULL);
+ xfree (tmp);
+ }
+ break;
+
default : pargs.err = ARGPARSE_PRINT_ERROR; break;
}
}
@@ -288,10 +304,18 @@ main( int argc, char **argv )
void
-g10_exit( int rc )
-{
- rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
- exit(rc );
+g10_exit (int rc)
+{
+ if (rc)
+ ;
+ else if (log_get_errorcount(0))
+ rc = 2;
+ else if (g10_errors_seen)
+ rc = 1;
+ else if (opt.assert_pubkey_algos && assert_pubkey_algo_false)
+ rc = 1;
+
+ exit (rc);
}
diff --git a/g10/keydb.h b/g10/keydb.h
index b18f6e93a..798c24da3 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -487,6 +487,7 @@ const char *key_origin_string (int origin);
/*-- keyid.c --*/
int pubkey_letter( int algo );
char *pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize);
+int compare_pubkey_string (const char *astr, const char *bstr);
#define PUBKEY_STRING_SIZE 32
u32 v3_keyid (gcry_mpi_t a, u32 *ki);
void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk );
diff --git a/g10/keyid.c b/g10/keyid.c
index 89bba0d7a..ce977de0b 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -140,6 +140,130 @@ pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize)
}
+/* Helper for compare_pubkey_string. This skips leading spaces,
+ * commas and optional condition operators and returns a pointer to
+ * the first non-space character or NULL in case of an error. The
+ * length of a prefix consisting of letters is then returned ar PFXLEN
+ * and the value of the number (e.g. 384 for "brainpoolP384r1") at
+ * NUMBER. R_LENGTH receives the entire length of the algorithm name
+ * which is terminated by a space, nul, or a comma. If R_CONDITION is
+ * not NULL, 0 is stored for a leading "=", 1 for a ">", 2 for a ">=",
+ * -1 for a "<", and -2 for a "<=". If R_CONDITION is NULL no
+ * condition prefix is allowed. */
+static const char *
+parse_one_algo_string (const char *str, size_t *pfxlen, unsigned int *number,
+ size_t *r_length, int *r_condition)
+{
+ int condition = 0;
+ const char *result;
+
+ while (spacep (str) || *str ==',')
+ str++;
+ if (!r_condition)
+ ;
+ else if (*str == '>' && str[1] == '=')
+ condition = 2, str += 2;
+ else if (*str == '>' )
+ condition = 1, str += 1;
+ else if (*str == '<' && str[1] == '=')
+ condition = -2, str += 2;
+ else if (*str == '<')
+ condition = -1, str += 1;
+ else if (*str == '=') /* Default. */
+ str += 1;
+
+ if (!alphap (str))
+ return NULL; /* Error. */
+
+ *pfxlen = 1;
+ for (result = str++; alphap (str); str++)
+ ++*pfxlen;
+ while (*str == '-' || *str == '+')
+ str++;
+ *number = atoi (str);
+ while (*str && !spacep (str) && *str != ',')
+ str++;
+
+ *r_length = str - result;
+ if (r_condition)
+ *r_condition = condition;
+ return result;
+}
+
+/* Helper for compare_pubkey_string. If BPARSED is set to 0 on
+ * return, an error in ASTR or BSTR was found and further checks are
+ * not possible. */
+static int
+compare_pubkey_string_part (const char *astr, const char *bstr_arg,
+ size_t *bparsed)
+{
+ const char *bstr = bstr_arg;
+ size_t alen, apfxlen, blen, bpfxlen;
+ unsigned int anumber, bnumber;
+ int condition;
+
+ *bparsed = 0;
+ astr = parse_one_algo_string (astr, &apfxlen, &anumber, &alen, &condition);
+ if (!astr)
+ return 0; /* Invalid algorithm name. */
+ bstr = parse_one_algo_string (bstr, &bpfxlen, &bnumber, &blen, &condition);
+ if (!bstr)
+ return 0; /* Invalid algorithm name. */
+ *bparsed = blen + (bstr - bstr_arg);
+ if (apfxlen != bpfxlen || ascii_strncasecmp (astr, bstr, apfxlen))
+ return 0; /* false. */
+ switch (condition)
+ {
+ case 2: return anumber >= bnumber;
+ case 1: return anumber > bnumber;
+ case -1: return anumber < bnumber;
+ case -2: return anumber <= bnumber;
+ }
+
+ return alen == blen && !ascii_strncasecmp (astr, bstr, alen);
+}
+
+
+/* Check whether ASTR matches the constraints given by BSTR. ASTR may
+ * be any algo string like "rsa2048", "ed25519" and BSTR may be a
+ * constraint which is in the simplest case just another algo string.
+ * BSTR may have more that one string in which case they are comma
+ * separated and any match will return true. It is possible to prefix
+ * BSTR with ">", ">=", "<=", or "<". That prefix operator is applied
+ * to the number part of the algorithm, i.e. the first sequence of
+ * digits found before end-of-string or a comma. Examples:
+ *
+ * | ASTR | BSTR | result |
+ * |----------+----------------------+--------|
+ * | rsa2048 | rsa2048 | true |
+ * | rsa2048 | >=rsa2048 | true |
+ * | rsa2048 | >rsa2048 | false |
+ * | ed25519 | >rsa1024 | false |
+ * | ed25519 | ed25519 | true |
+ * | nistp384 | >nistp256 | true |
+ * | nistp521 | >=rsa3072, >nistp384 | true |
+ */
+int
+compare_pubkey_string (const char *astr, const char *bstr)
+{
+ size_t bparsed;
+ int result;
+
+ while (*bstr)
+ {
+ result = compare_pubkey_string_part (astr, bstr, &bparsed);
+ if (result)
+ return 1;
+ if (!bparsed)
+ return 0; /* Syntax error in ASTR or BSTR. */
+ bstr += bparsed;
+ }
+
+ return 0;
+}
+
+
+
/* Hash a public key and allow to specify the to be used format.
* Note that if the v5 format is requested for a v4 key, a 0x04 as
* version is hashed instead of the 0x05. */
diff --git a/g10/main.h b/g10/main.h
index b29e23e51..2482fbde2 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -84,6 +84,7 @@ struct weakhash
/*-- gpg.c --*/
extern int g10_errors_seen;
extern int assert_signer_true;
+extern int assert_pubkey_algo_false;
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void g10_exit(int rc) __attribute__ ((__noreturn__));
@@ -494,6 +495,7 @@ int verify_signatures (ctrl_t ctrl, int nfiles, char **files );
int verify_files (ctrl_t ctrl, int nfiles, char **files );
int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp);
void check_assert_signer_list (const char *mainpkhex, const char *pkhex);
+void check_assert_pubkey_algo (const char *algostr, const char *pkhex);
/*-- decrypt.c --*/
int decrypt_message (ctrl_t ctrl, const char *filename );
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 430d7ff08..5f3f6df86 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1876,6 +1876,8 @@ check_sig_and_print (CTX c, kbnode_t node)
const void *extrahash = NULL;
size_t extrahashlen = 0;
kbnode_t included_keyblock = NULL;
+ char pkstrbuf[PUBKEY_STRING_SIZE] = { 0 };
+
if (opt.skip_verify)
{
@@ -2409,8 +2411,14 @@ check_sig_and_print (CTX c, kbnode_t node)
show_notation (sig, 0, 2, 0);
}
+ /* Fill PKSTRBUF with the algostring in case we later need it. */
+ if (pk)
+ pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
+
/* For good signatures print the VALIDSIG status line. */
- if (!rc && (is_status_enabled () || opt.assert_signer_list) && pk)
+ if (!rc && (is_status_enabled ()
+ || opt.assert_signer_list
+ || opt.assert_pubkey_algos) && pk)
{
char pkhex[MAX_FINGERPRINT_LEN*2+1];
char mainpkhex[MAX_FINGERPRINT_LEN*2+1];
@@ -2432,6 +2440,8 @@ check_sig_and_print (CTX c, kbnode_t node)
mainpkhex);
/* Handle the --assert-signer option. */
check_assert_signer_list (mainpkhex, pkhex);
+ /* Handle the --assert-pubkey-algo option. */
+ check_assert_pubkey_algo (pkstrbuf, pkhex);
}
/* Print compliance warning for Good signatures. */
@@ -2464,13 +2474,6 @@ check_sig_and_print (CTX c, kbnode_t node)
if (opt.verbose)
{
- char pkstrbuf[PUBKEY_STRING_SIZE];
-
- if (pk)
- pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
- else
- *pkstrbuf = 0;
-
log_info (_("%s signature, digest algorithm %s%s%s\n"),
sig->sig_class==0x00?_("binary"):
sig->sig_class==0x01?_("textmode"):_("unknown"),
diff --git a/g10/options.h b/g10/options.h
index 146b78361..1e1110334 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -241,6 +241,10 @@ struct
* modify to be uppercase if they represent a fingerrint */
strlist_t assert_signer_list;
+ /* A single string with the comma delimited args from
+ * --assert-pubkey_algo. */
+ char *assert_pubkey_algos;
+
struct
{
/* If set, require an 0x19 backsig to be present on signatures
diff --git a/g10/t-keydb-get-keyblock.c b/g10/t-keydb-get-keyblock.c
index e40be9cc1..90ce6e9a6 100644
--- a/g10/t-keydb-get-keyblock.c
+++ b/g10/t-keydb-get-keyblock.c
@@ -67,12 +67,3 @@ do_test (int argc, char *argv[])
release_kbnode (kb1);
xfree (ctrl);
}
-
-int assert_signer_true = 0;
-
-void
-check_assert_signer_list (const char *mainpkhex, const char *pkhex)
-{
- (void)mainpkhex;
- (void)pkhex;
-}
diff --git a/g10/t-keydb.c b/g10/t-keydb.c
index 9055d5b94..4c78dac48 100644
--- a/g10/t-keydb.c
+++ b/g10/t-keydb.c
@@ -105,13 +105,3 @@ do_test (int argc, char *argv[])
keydb_release (hd2);
xfree (ctrl);
}
-
-
-int assert_signer_true = 0;
-
-void
-check_assert_signer_list (const char *mainpkhex, const char *pkhex)
-{
- (void)mainpkhex;
- (void)pkhex;
-}
diff --git a/g10/t-keyid.c b/g10/t-keyid.c
new file mode 100644
index 000000000..d42399027
--- /dev/null
+++ b/g10/t-keyid.c
@@ -0,0 +1,129 @@
+/* t-keyid.c - Tests for keyid.c.
+ * Copyright (C) 2024 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define LEAN_T_SUPPORT 1
+
+#define PGM "t-keyid"
+
+#include "gpg.h"
+#include "keydb.h"
+#include "../common/t-support.h"
+
+
+
+static int verbose;
+
+
+static void
+test_compare_pubkey_string (void)
+{
+ static struct { const char *astr; const char *bstr; int expected; } t[] =
+ {
+ { "rsa2048" , "rsa2048" , 1 },
+ { "rsa2048" , ">=rsa2048" , 1 },
+ { "rsa2048" , ">rsa2048" , 0 },
+ { "ed25519" , ">rsa1024" , 0 },
+ { "ed25519" , "ed25519" , 1 },
+ { "ed25519" , ",,,=ed25519" , 1 },
+ { "nistp384" , ">nistp256" , 1 },
+ { "nistp521" , ">=rsa3072, >nistp384", 1 },
+ { " nistp521" , ">=rsa3072, >nistp384 ", 1 },
+ { " nistp521 " , " >=rsa3072, >nistp384 ", 1 },
+ { " =nistp521 " , " >=rsa3072, >nistp384,,", 1 },
+ { "nistp384" , ">nistp384" , 0 },
+ { "nistp384" , ">=nistp384" , 1 },
+ { "brainpoolP384" , ">=brainpoolp256", 1 },
+ { "brainpoolP384" , ">brainpoolp384" , 0 },
+ { "brainpoolP384" , ">=brainpoolp384", 1 },
+ { "brainpoolP256r1", ">brainpoolp256r1", 0 },
+ { "brainpoolP384r1", ">brainpoolp384r1" , 0 },
+ { "brainpoolP384r1", ">=brainpoolp384r1", 1 },
+ { "brainpoolP384r1", ">=brainpoolp384" , 1 },
+ { "", "", 0}
+ };
+ int idx;
+ int result;
+
+ for (idx=0; idx < DIM(t); idx++)
+ {
+ result = compare_pubkey_string (t[idx].astr, t[idx].bstr);
+ if (result != t[idx].expected)
+ {
+ fail (idx);
+ if (verbose)
+ log_debug ("\"%s\", \"%s\" want %d got %d\n",
+ t[idx].astr, t[idx].bstr, t[idx].expected, result);
+ }
+ }
+
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+
+ no_exit_on_fail = 1;
+
+ if (argc)
+ { argc--; argv++; }
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ {
+ fputs ("usage: " PGM " [FILE]\n"
+ "Options:\n"
+ " --verbose Print timings etc.\n"
+ " --debug Flyswatter\n"
+ , stdout);
+ exit (0);
+ }
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose++;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--debug"))
+ {
+ verbose += 2;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ {
+ fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
+ exit (1);
+ }
+ }
+
+ test_compare_pubkey_string ();
+
+ return !!errcount;
+}
diff --git a/g10/t-stutter.c b/g10/t-stutter.c
index 7b2ea4b37..503a92004 100644
--- a/g10/t-stutter.c
+++ b/g10/t-stutter.c
@@ -611,12 +611,3 @@ do_test (int argc, char *argv[])
xfree (filename);
}
-
-int assert_signer_true = 0;
-
-void
-check_assert_signer_list (const char *mainpkhex, const char *pkhex)
-{
- (void)mainpkhex;
- (void)pkhex;
-}
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index 6ae0f4eb7..d9bead754 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -43,6 +43,9 @@
#include "call-agent.h"
int g10_errors_seen;
+int assert_signer_true = 0;
+int assert_pubkey_algo_false = 0;
+
void
@@ -580,3 +583,18 @@ impex_filter_getval (void *cookie, const char *propname)
(void)propname;
return NULL;
}
+
+
+void
+check_assert_signer_list (const char *mainpkhex, const char *pkhex)
+{
+ (void)mainpkhex;
+ (void)pkhex;
+}
+
+void
+check_assert_pubkey_algo (const char *algostr, const char *pkhex)
+{
+ (void)algostr;
+ (void)pkhex;
+}
diff --git a/g10/test.c b/g10/test.c
index 648148a10..f6c697a35 100644
--- a/g10/test.c
+++ b/g10/test.c
@@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
diff --git a/g10/verify.c b/g10/verify.c
index e9792939d..1c3de767c 100644
--- a/g10/verify.c
+++ b/g10/verify.c
@@ -333,7 +333,7 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
assert_signer_true = 1;
write_status_text (STATUS_ASSERT_SIGNER, item->d);
if (!opt.quiet)
- log_info ("signer '%s' matched\n", item->d);
+ log_info ("asserted signer '%s'\n", item->d);
goto leave;
}
}
@@ -388,7 +388,7 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
assert_signer_true = 1;
write_status_text (STATUS_ASSERT_SIGNER, p);
if (!opt.quiet)
- log_info ("signer '%s' matched '%s', line %d\n",
+ log_info ("asserted signer '%s' (%s:%d)\n",
p, fname, lnr);
goto leave;
}
@@ -405,3 +405,32 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
leave:
es_fclose (fp);
}
+
+
+/* This function shall be called with the signer's public key
+ * algorithm ALGOSTR iff a signature is fully valid. If the option
+ * --assert-pubkey-algo is active the functions checks whether the
+ * signing key's algo is valid according to that list; in this case a
+ * global flag is set. */
+void
+check_assert_pubkey_algo (const char *algostr, const char *pkhex)
+{
+ if (!opt.assert_pubkey_algos)
+ return; /* Nothing to do. */
+
+ if (compare_pubkey_string (algostr, opt.assert_pubkey_algos))
+ {
+ write_status_strings (STATUS_ASSERT_PUBKEY_ALGO,
+ pkhex, " 1 ", algostr, NULL);
+ if (!opt.quiet)
+ log_info ("asserted signer '%s' with algo %s\n", pkhex, algostr);
+ }
+ else
+ {
+ if (!opt.quiet)
+ log_info ("denied signer '%s' with algo %s\n", pkhex, algostr);
+ assert_pubkey_algo_false = 1;
+ write_status_strings (STATUS_ASSERT_PUBKEY_ALGO,
+ pkhex, " 0 ", algostr, NULL);
+ }
+}