mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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
This commit is contained in:
parent
5842eee805
commit
302afcb6f6
@ -54,6 +54,7 @@ enum
|
|||||||
STATUS_NEED_PASSPHRASE,
|
STATUS_NEED_PASSPHRASE,
|
||||||
STATUS_VALIDSIG,
|
STATUS_VALIDSIG,
|
||||||
STATUS_ASSERT_SIGNER,
|
STATUS_ASSERT_SIGNER,
|
||||||
|
STATUS_ASSERT_PUBKEY_ALGO,
|
||||||
STATUS_SIG_ID,
|
STATUS_SIG_ID,
|
||||||
STATUS_ENC_TO,
|
STATUS_ENC_TO,
|
||||||
STATUS_NODATA,
|
STATUS_NODATA,
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#ifndef GNUPG_COMMON_T_SUPPORT_H
|
#ifndef GNUPG_COMMON_T_SUPPORT_H
|
||||||
#define GNUPG_COMMON_T_SUPPORT_H 1
|
#define GNUPG_COMMON_T_SUPPORT_H 1
|
||||||
|
|
||||||
|
#ifndef LEAN_T_SUPPORT
|
||||||
|
|
||||||
#ifdef GCRYPT_VERSION
|
#ifdef GCRYPT_VERSION
|
||||||
#error The regression tests should not include with gcrypt.h
|
#error The regression tests should not include with gcrypt.h
|
||||||
#endif
|
#endif
|
||||||
@ -45,11 +47,6 @@
|
|||||||
# define getenv(a) (NULL)
|
# define getenv(a) (NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DIM
|
|
||||||
# define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
|
||||||
# define DIMof(type,member) DIM(((type *)0)->member)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Replacement prototypes. */
|
/* Replacement prototypes. */
|
||||||
void *gcry_xmalloc (size_t n);
|
void *gcry_xmalloc (size_t n);
|
||||||
@ -65,6 +62,12 @@ void gcry_free (void *a);
|
|||||||
#define xstrdup(a) gcry_xstrdup ( (a) )
|
#define xstrdup(a) gcry_xstrdup ( (a) )
|
||||||
#define xfree(a) gcry_free ( (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. */
|
/* Macros to print the result of a test. */
|
||||||
#define pass() do { ; } while(0)
|
#define pass() do { ; } while(0)
|
||||||
|
@ -527,6 +527,12 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||||||
--assert-signer is used. The fingerprint is printed with
|
--assert-signer is used. The fingerprint is printed with
|
||||||
uppercase hex digits.
|
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>
|
*** SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
|
||||||
This is emitted only for signatures of class 0 or 1 which have
|
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
|
been verified okay. The string is a signature id and may be used
|
||||||
|
23
doc/gpg.texi
23
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
|
signature has been encountered, is valid, and the key matches one of
|
||||||
the fingerprints given by this option.
|
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}
|
@item --auto-key-locate @var{mechanisms}
|
||||||
@itemx --no-auto-key-locate
|
@itemx --no-auto-key-locate
|
||||||
|
@ -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,
|
@file{-&n}, where n is a non-negative decimal number,
|
||||||
refer to the file descriptor n and not to a file with that name.
|
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
|
@end table
|
||||||
|
|
||||||
@mansect return value
|
@mansect return value
|
||||||
@ -190,4 +194,3 @@ The default keyring with the allowed keys.
|
|||||||
@mansect see also
|
@mansect see also
|
||||||
@command{gpg}(1)
|
@command{gpg}(1)
|
||||||
@include see-also-note.texi
|
@include see-also-note.texi
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ gpgv_LDFLAGS =
|
|||||||
|
|
||||||
|
|
||||||
t_common_ldadd =
|
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_SOURCES = t-rmd160.c rmd160.c
|
||||||
t_rmd160_LDADD = $(t_common_ldadd)
|
t_rmd160_LDADD = $(t_common_ldadd)
|
||||||
t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source)
|
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) \
|
t_stutter_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \
|
||||||
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
|
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \
|
||||||
$(LIBICONV) $(t_common_ldadd)
|
$(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
|
$(PROGRAMS): $(needed_libs) ../common/libgpgrl.a
|
||||||
|
39
g10/gpg.c
39
g10/gpg.c
@ -451,6 +451,7 @@ enum cmd_and_opt_values
|
|||||||
oCompatibilityFlags,
|
oCompatibilityFlags,
|
||||||
oAddDesigRevoker,
|
oAddDesigRevoker,
|
||||||
oAssertSigner,
|
oAssertSigner,
|
||||||
|
oAssertPubkeyAlgo,
|
||||||
oKbxBufferSize,
|
oKbxBufferSize,
|
||||||
|
|
||||||
oNoop
|
oNoop
|
||||||
@ -715,6 +716,7 @@ static gpgrt_opt_t opts[] = {
|
|||||||
#endif
|
#endif
|
||||||
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
|
ARGPARSE_s_s (oAddDesigRevoker, "add-desig-revoker", "@"),
|
||||||
ARGPARSE_s_s (oAssertSigner, "assert-signer", "@"),
|
ARGPARSE_s_s (oAssertSigner, "assert-signer", "@"),
|
||||||
|
ARGPARSE_s_s (oAssertPubkeyAlgo,"assert-pubkey-algo", "@"),
|
||||||
|
|
||||||
ARGPARSE_header ("Input", N_("Options controlling the input")),
|
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. */
|
/* Can be set to true to force gpg to return with EXIT_FAILURE. */
|
||||||
int g10_errors_seen = 0;
|
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. */
|
* gpg will be forced to return EXIT_FAILURE. */
|
||||||
int assert_signer_true = 0;
|
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 =
|
static int utf8_strings =
|
||||||
@ -3770,6 +3775,18 @@ main (int argc, char **argv)
|
|||||||
add_to_strlist (&opt.assert_signer_list, pargs.r.ret_str);
|
add_to_strlist (&opt.assert_signer_list, pargs.r.ret_str);
|
||||||
break;
|
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:
|
case oKbxBufferSize:
|
||||||
keybox_set_buffersize (pargs.r.ret_ulong, 0);
|
keybox_set_buffersize (pargs.r.ret_ulong, 0);
|
||||||
break;
|
break;
|
||||||
@ -5472,6 +5489,17 @@ emergency_cleanup (void)
|
|||||||
void
|
void
|
||||||
g10_exit( int 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_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.
|
/* 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
|
* Note that write_status_failure will never print a second failure
|
||||||
* status line. */
|
* status line. */
|
||||||
@ -5496,15 +5524,6 @@ g10_exit( int rc )
|
|||||||
gnupg_block_all_signals ();
|
gnupg_block_all_signals ();
|
||||||
emergency_cleanup ();
|
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);
|
exit (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
g10/gpgv.c
30
g10/gpgv.c
@ -68,6 +68,7 @@ enum cmd_and_opt_values {
|
|||||||
oWeakDigest,
|
oWeakDigest,
|
||||||
oEnableSpecialFilenames,
|
oEnableSpecialFilenames,
|
||||||
oDebug,
|
oDebug,
|
||||||
|
oAssertPubkeyAlgo,
|
||||||
aTest
|
aTest
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,6 +92,7 @@ static gpgrt_opt_t opts[] = {
|
|||||||
N_("|ALGO|reject signatures made with ALGO")),
|
N_("|ALGO|reject signatures made with ALGO")),
|
||||||
ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"),
|
ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"),
|
||||||
ARGPARSE_s_s (oDebug, "debug", "@"),
|
ARGPARSE_s_s (oDebug, "debug", "@"),
|
||||||
|
ARGPARSE_s_s (oAssertPubkeyAlgo,"assert-pubkey-algo", "@"),
|
||||||
|
|
||||||
ARGPARSE_end ()
|
ARGPARSE_end ()
|
||||||
};
|
};
|
||||||
@ -119,6 +121,7 @@ static struct debug_flags_s debug_flags [] =
|
|||||||
|
|
||||||
int g10_errors_seen = 0;
|
int g10_errors_seen = 0;
|
||||||
int assert_signer_true = 0;
|
int assert_signer_true = 0;
|
||||||
|
int assert_pubkey_algo_false = 0;
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
make_libversion (const char *libname, const char *(*getfnc)(const char*))
|
make_libversion (const char *libname, const char *(*getfnc)(const char*))
|
||||||
@ -251,6 +254,19 @@ main( int argc, char **argv )
|
|||||||
case oEnableSpecialFilenames:
|
case oEnableSpecialFilenames:
|
||||||
enable_special_filenames ();
|
enable_special_filenames ();
|
||||||
break;
|
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;
|
default : pargs.err = ARGPARSE_PRINT_ERROR; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,10 +304,18 @@ main( int argc, char **argv )
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
g10_exit( int rc )
|
g10_exit (int rc)
|
||||||
{
|
{
|
||||||
rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
|
if (rc)
|
||||||
exit(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -487,6 +487,7 @@ const char *key_origin_string (int origin);
|
|||||||
/*-- keyid.c --*/
|
/*-- keyid.c --*/
|
||||||
int pubkey_letter( int algo );
|
int pubkey_letter( int algo );
|
||||||
char *pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize);
|
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
|
#define PUBKEY_STRING_SIZE 32
|
||||||
u32 v3_keyid (gcry_mpi_t a, u32 *ki);
|
u32 v3_keyid (gcry_mpi_t a, u32 *ki);
|
||||||
void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk );
|
void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk );
|
||||||
|
124
g10/keyid.c
124
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.
|
/* 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
|
* Note that if the v5 format is requested for a v4 key, a 0x04 as
|
||||||
* version is hashed instead of the 0x05. */
|
* version is hashed instead of the 0x05. */
|
||||||
|
@ -84,6 +84,7 @@ struct weakhash
|
|||||||
/*-- gpg.c --*/
|
/*-- gpg.c --*/
|
||||||
extern int g10_errors_seen;
|
extern int g10_errors_seen;
|
||||||
extern int assert_signer_true;
|
extern int assert_signer_true;
|
||||||
|
extern int assert_pubkey_algo_false;
|
||||||
|
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
||||||
void g10_exit(int rc) __attribute__ ((__noreturn__));
|
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 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);
|
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_signer_list (const char *mainpkhex, const char *pkhex);
|
||||||
|
void check_assert_pubkey_algo (const char *algostr, const char *pkhex);
|
||||||
|
|
||||||
/*-- decrypt.c --*/
|
/*-- decrypt.c --*/
|
||||||
int decrypt_message (ctrl_t ctrl, const char *filename );
|
int decrypt_message (ctrl_t ctrl, const char *filename );
|
||||||
|
@ -1876,6 +1876,8 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
const void *extrahash = NULL;
|
const void *extrahash = NULL;
|
||||||
size_t extrahashlen = 0;
|
size_t extrahashlen = 0;
|
||||||
kbnode_t included_keyblock = NULL;
|
kbnode_t included_keyblock = NULL;
|
||||||
|
char pkstrbuf[PUBKEY_STRING_SIZE] = { 0 };
|
||||||
|
|
||||||
|
|
||||||
if (opt.skip_verify)
|
if (opt.skip_verify)
|
||||||
{
|
{
|
||||||
@ -2409,8 +2411,14 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
show_notation (sig, 0, 2, 0);
|
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. */
|
/* 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 pkhex[MAX_FINGERPRINT_LEN*2+1];
|
||||||
char mainpkhex[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);
|
mainpkhex);
|
||||||
/* Handle the --assert-signer option. */
|
/* Handle the --assert-signer option. */
|
||||||
check_assert_signer_list (mainpkhex, pkhex);
|
check_assert_signer_list (mainpkhex, pkhex);
|
||||||
|
/* Handle the --assert-pubkey-algo option. */
|
||||||
|
check_assert_pubkey_algo (pkstrbuf, pkhex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print compliance warning for Good signatures. */
|
/* Print compliance warning for Good signatures. */
|
||||||
@ -2464,13 +2474,6 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
|
|
||||||
if (opt.verbose)
|
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"),
|
log_info (_("%s signature, digest algorithm %s%s%s\n"),
|
||||||
sig->sig_class==0x00?_("binary"):
|
sig->sig_class==0x00?_("binary"):
|
||||||
sig->sig_class==0x01?_("textmode"):_("unknown"),
|
sig->sig_class==0x01?_("textmode"):_("unknown"),
|
||||||
|
@ -241,6 +241,10 @@ struct
|
|||||||
* modify to be uppercase if they represent a fingerrint */
|
* modify to be uppercase if they represent a fingerrint */
|
||||||
strlist_t assert_signer_list;
|
strlist_t assert_signer_list;
|
||||||
|
|
||||||
|
/* A single string with the comma delimited args from
|
||||||
|
* --assert-pubkey_algo. */
|
||||||
|
char *assert_pubkey_algos;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/* If set, require an 0x19 backsig to be present on signatures
|
/* If set, require an 0x19 backsig to be present on signatures
|
||||||
|
@ -67,12 +67,3 @@ do_test (int argc, char *argv[])
|
|||||||
release_kbnode (kb1);
|
release_kbnode (kb1);
|
||||||
xfree (ctrl);
|
xfree (ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int assert_signer_true = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|
||||||
{
|
|
||||||
(void)mainpkhex;
|
|
||||||
(void)pkhex;
|
|
||||||
}
|
|
||||||
|
@ -105,13 +105,3 @@ do_test (int argc, char *argv[])
|
|||||||
keydb_release (hd2);
|
keydb_release (hd2);
|
||||||
xfree (ctrl);
|
xfree (ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int assert_signer_true = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|
||||||
{
|
|
||||||
(void)mainpkhex;
|
|
||||||
(void)pkhex;
|
|
||||||
}
|
|
||||||
|
129
g10/t-keyid.c
Normal file
129
g10/t-keyid.c
Normal file
@ -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;
|
||||||
|
}
|
@ -611,12 +611,3 @@ do_test (int argc, char *argv[])
|
|||||||
|
|
||||||
xfree (filename);
|
xfree (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
int assert_signer_true = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|
||||||
{
|
|
||||||
(void)mainpkhex;
|
|
||||||
(void)pkhex;
|
|
||||||
}
|
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#include "call-agent.h"
|
#include "call-agent.h"
|
||||||
|
|
||||||
int g10_errors_seen;
|
int g10_errors_seen;
|
||||||
|
int assert_signer_true = 0;
|
||||||
|
int assert_pubkey_algo_false = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -580,3 +583,18 @@ impex_filter_getval (void *cookie, const char *propname)
|
|||||||
(void)propname;
|
(void)propname;
|
||||||
return NULL;
|
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;
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
33
g10/verify.c
33
g10/verify.c
@ -333,7 +333,7 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|||||||
assert_signer_true = 1;
|
assert_signer_true = 1;
|
||||||
write_status_text (STATUS_ASSERT_SIGNER, item->d);
|
write_status_text (STATUS_ASSERT_SIGNER, item->d);
|
||||||
if (!opt.quiet)
|
if (!opt.quiet)
|
||||||
log_info ("signer '%s' matched\n", item->d);
|
log_info ("asserted signer '%s'\n", item->d);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|||||||
assert_signer_true = 1;
|
assert_signer_true = 1;
|
||||||
write_status_text (STATUS_ASSERT_SIGNER, p);
|
write_status_text (STATUS_ASSERT_SIGNER, p);
|
||||||
if (!opt.quiet)
|
if (!opt.quiet)
|
||||||
log_info ("signer '%s' matched '%s', line %d\n",
|
log_info ("asserted signer '%s' (%s:%d)\n",
|
||||||
p, fname, lnr);
|
p, fname, lnr);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -405,3 +405,32 @@ check_assert_signer_list (const char *mainpkhex, const char *pkhex)
|
|||||||
leave:
|
leave:
|
||||||
es_fclose (fp);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user