From af9a1b5599f9b6832c1f0481e56afe47acfab2be Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 27 Jun 2022 18:02:03 +0200 Subject: [PATCH] agent: Do not consider --min-passphrase-len for the magic wand. * agent/call-pinentry.c (generate_pin): Lock to exactly 30 octets. * g10/gpg.c (main) : Add Level 30. (cherry picked from commit ae2f1f0785e429d6dbb577a1fcf9a880aaff8e49) --- agent/call-pinentry.c | 21 +++++++++++---------- doc/gpg.texi | 7 ++++--- g10/gpg.c | 24 +++++++++++++++++++++++- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 5fcf98b49..2fdda64a8 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -57,7 +57,9 @@ * passphrase will be rendered as zbase32 which results for 150 bits * in a string of 30 characters. That fits nicely into the 5 * character blocking which pinentry can do. 128 bits would actually - * be sufficient but can't be formatted nicely. */ + * be sufficient but can't be formatted nicely. Please do not change + * this value because pattern check files may let such passwords + * always pass. */ #define DEFAULT_GENPIN_BITS 150 /* The assuan context of the current pinentry. */ @@ -834,21 +836,20 @@ estimate_passphrase_quality (const char *pw) /* Generate a random passphrase in zBase32 encoding (RFC-6189) to be - * used by Pinentry to suggest a passphrase. */ + * used by Pinentry to suggest a passphrase. Note that we have the + * same algorithm in gpg.c for --gen-random at level 30. It is + * important that we always output exactly 30 characters to match the + * special exception we have in the pattern file for symmetric + * encryption. */ static char * generate_pin (void) { - unsigned int nbits = opt.min_passphrase_len * 8; - size_t nbytes; + unsigned int nbits = DEFAULT_GENPIN_BITS; + size_t nbytes = nbytes = (nbits + 7) / 8; void *rand; char *generated; - if (nbits < 128) - nbits = DEFAULT_GENPIN_BITS; - - nbytes = (nbits + 7) / 8; - - rand = gcry_random_bytes_secure (nbytes, GCRY_STRONG_RANDOM); + rand = gcry_random_bytes_secure (nbytes, GCRY_STRONG_RANDOM); if (!rand) { log_error ("failed to generate random pin\n"); diff --git a/doc/gpg.texi b/doc/gpg.texi index 4f09d4e2c..2958a2ebf 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -609,13 +609,14 @@ Print message digest of algorithm @var{algo} for all given files or STDIN. With the second form (or a deprecated "*" for @var{algo}) digests for all available algorithms are printed. -@item --gen-random @var{0|1|2} @var{count} +@item --gen-random @var{0|1|2|16|30} @var{count} @opindex gen-random Emit @var{count} random bytes of the given quality level 0, 1 or 2. If @var{count} is not given or zero, an endless sequence of random bytes will be emitted. If used with @option{--armor} the output will be -base64 encoded. PLEASE, don't use this command unless you know what -you are doing; it may remove precious entropy from the system! +base64 encoded. The special level 16 uses a quality level of 1 and +outputs and endless stream of hex-encoded octets. The special level +30 outputs random as 30 zBase-32 characters. @item --gen-prime @var{mode} @var{bits} @opindex gen-prime diff --git a/g10/gpg.c b/g10/gpg.c index dbecf9170..97ca93314 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -62,6 +62,7 @@ #include "tofu.h" #include "../common/init.h" #include "../common/mbox-util.h" +#include "../common/zb32.h" #include "../common/shareddefs.h" #include "../common/compliance.h" @@ -4910,8 +4911,29 @@ main (int argc, char **argv) if (hexhack) level = 1; + /* Level 30 uses the same algorithm as our magic wand in + * pinentry/gpg-agent. */ + if (level == 30) + { + unsigned int nbits = 150; + size_t nbytes = (nbits + 7) / 8; + void *rand; + char *generated; + + rand = gcry_random_bytes_secure (nbytes, GCRY_STRONG_RANDOM); + if (!rand) + log_fatal ("failed to generate random password\n"); + + generated = zb32_encode (rand, nbits); + gcry_free (rand); + es_fputs (generated, es_stdout); + es_putc ('\n', es_stdout); + xfree (generated); + break; + } + if (argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0) - wrong_args ("--gen-random 0|1|2 [count]"); + wrong_args ("--gen-random 0|1|2|16|30 [count]"); while (endless || count) {