aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keyid.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2024-02-10 13:24:50 +0000
committerWerner Koch <[email protected]>2024-02-10 13:26:55 +0000
commit302afcb6f6af1dc88357acacfaa6829f0717b1c6 (patch)
treef198426cf8c1713df2c7f0ae6939fc9fad12667e /g10/keyid.c
parentdoc: Suggest the use of a fingerprint for --default-key. (diff)
downloadgnupg-302afcb6f6af1dc88357acacfaa6829f0717b1c6.tar.gz
gnupg-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
Diffstat (limited to 'g10/keyid.c')
-rw-r--r--g10/keyid.c124
1 files changed, 124 insertions, 0 deletions
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. */