gpg: New option --chunk-size.

* g10/gpg.c (opts): New option --chunk-size.
(oChunkSize): New const.
(build_list_aead_test_algo, build_list_aead_algo_name): New.
(my_strusage): List AEAD algos.
(main): Implement --chunk-size..
* g10/options.h (struct opt): Add field 'chunk_size'.
(DBG_IPC): Remove duplicated macro.
* g10/main.h (DEFAULT_AEAD_ALGO): Depend on Libgcrypt version.
* g10/misc.c (openpgp_aead_test_algo): Ditto.

* g10/cipher-aead.c: Silence if not in debug mode.
* g10/decrypt-data.c: Ditto.
--

And that new option immediatley revealed bugs in our chunking code :-(.
This commit is contained in:
Werner Koch 2018-01-23 19:08:16 +01:00
parent 112e02ee89
commit f3ef8b0dca
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 185 additions and 59 deletions

View File

@ -2255,6 +2255,16 @@ works properly with such messages, there is often a desire to set a
maximum file size that will be generated before processing is forced to
stop by the OS limits. Defaults to 0, which means "no limit".
@item --chunk-size @var{n}
@opindex chunk-size
The AEAD encryption mode encrypts the data in chunks so that a
receiving side can check for transmission errors or tampering at the
end of each chunk and does not need to delay this until all data has
been received. The used chunk size is 2^@var{n} byte. The lowest
allowed value for @var{n} is 6 (64 byte) and the largest is 62 (4
EiB). The default value for @var{n} is 30 which creates chunks not
larger than 1 GiB.
@item --input-size-hint @var{n}
@opindex input-size-hint
This option can be used to tell GPG the size of the input data in
@ -2592,6 +2602,16 @@ is the default.
@itemx --no-force-v4-certs
These options are obsolete and have no effect since GnuPG 2.1.
@item --force-aead
@opindex force-aead
Force the use of AEAD encryption over MDC encryption. AEAD is a
modern and faster way to do authenticated encrytion than the old MDC
method. See also options @option{--aead-algo} and
@option{--chunk-size}.
This option requires the use of option @option{--rfc4880bis} to
declare that a not yet standardized feature is used.
@item --force-mdc
@opindex force-mdc
Force the use of encryption with a modification detection code. This
@ -2623,6 +2643,16 @@ preferences, as GPG will only select an algorithm that is usable by
all recipients. The most highly ranked cipher in this list is also
used for the @option{--symmetric} encryption command.
@item --personal-aead-preferences @var{string}
@opindex personal-aead-preferences
Set the list of personal AEAD preferences to @var{string}. Use
@command{@gpgname --version} to get a list of available algorithms,
and use @code{none} to set no preference at all. This allows the user
to safely override the algorithm chosen by the recipient key
preferences, as GPG will only select an algorithm that is usable by
all recipients. The most highly ranked cipher in this list is also
used for the @option{--symmetric} encryption command.
@item --personal-digest-preferences @var{string}
@opindex personal-digest-preferences
Set the list of personal digest preferences to @var{string}. Use
@ -2981,17 +3011,28 @@ Use @var{name} as cipher algorithm. Running the program with the
command @option{--version} yields a list of supported algorithms. If
this is not used the cipher algorithm is selected from the preferences
stored with the key. In general, you do not want to use this option as
it allows you to violate the OpenPGP standard.
it allows you to violate the OpenPGP standard. The option
@option{--personal-cipher-preferences} is the safe way to accomplish the
same thing.
@item --aead-algo @var{name}
@opindex aead-algo
Specify that the AEAD algorithm @var{name} is to be used. This is
useful for symmetric encryption where no key preference are available
to select the AEAD algorithm. Runing @command{@gpgname} with option
@option{--version} shows the available AEAD algorithms. In general,
you do not want to use this option as it allows you to violate the
OpenPGP standard. The option @option{--personal-aead-preferences} is
the safe way to accomplish the same thing.
@item --digest-algo @var{name}
@opindex digest-algo
Use @var{name} as the message digest algorithm. Running the program
with the command @option{--version} yields a list of supported algorithms. In
general, you do not want to use this option as it allows you to
violate the OpenPGP standard. @option{--personal-digest-preferences} is the
safe way to accomplish the same thing.
with the command @option{--version} yields a list of supported
algorithms. In general, you do not want to use this option as it
allows you to violate the OpenPGP standard. The option
@option{--personal-digest-preferences} is the safe way to accomplish
the same thing.
@item --compress-algo @var{name}
@opindex compress-algo
@ -3013,8 +3054,9 @@ significant in low memory situations. Note, however, that PGP (all
versions) only supports ZIP compression. Using any algorithm other
than ZIP or "none" will make the message unreadable with PGP. In
general, you do not want to use this option as it allows you to
violate the OpenPGP standard. @option{--personal-compress-preferences} is the
safe way to accomplish the same thing.
violate the OpenPGP standard. The option
@option{--personal-compress-preferences} is the safe way to accomplish
the same thing.
@item --cert-digest-algo @var{name}
@opindex cert-digest-algo

View File

@ -86,7 +86,8 @@ set_additional_data (cipher_filter_context_t *cfx, int final)
ad[19] = cfx->total >> 8;
ad[20] = cfx->total;
}
log_printhex (ad, final? 21 : 13, "authdata:");
if (DBG_CRYPTO)
log_printhex (ad, final? 21 : 13, "authdata:");
return gcry_cipher_authenticate (cfx->cipher_hd, ad, final? 21 : 13);
}
@ -124,7 +125,8 @@ set_nonce (cipher_filter_context_t *cfx)
nonce[i++] ^= cfx->chunkindex >> 8;
nonce[i++] ^= cfx->chunkindex;
log_printhex (nonce, 15, "nonce:");
if (DBG_CRYPTO)
log_printhex (nonce, 15, "nonce:");
return gcry_cipher_setiv (cfx->cipher_hd, nonce, i);
}
@ -149,7 +151,8 @@ write_header (cipher_filter_context_t *cfx, iobuf_t a)
if (err)
goto leave;
cfx->chunkbyte = 10;
log_assert (opt.chunk_size >= 6 && opt.chunk_size <= 62);
cfx->chunkbyte = opt.chunk_size - 6;
cfx->chunksize = (uint64_t)1 << (cfx->chunkbyte + 6);
cfx->chunklen = 0;
cfx->bufsize = AEAD_ENC_BUFFER_SIZE;
@ -170,8 +173,9 @@ write_header (cipher_filter_context_t *cfx, iobuf_t a)
pkt.pkttype = PKT_ENCRYPTED_AEAD;
pkt.pkt.encrypted = &ed;
log_debug ("aead packet: len=%lu extralen=%d\n",
(unsigned long)ed.len, ed.extralen);
if (DBG_FILTER)
log_debug ("aead packet: len=%lu extralen=%d\n",
(unsigned long)ed.len, ed.extralen);
write_status_printf (STATUS_BEGIN_ENCRYPTION, "0 %d %d",
cfx->dek->algo, ed.aead_algo);
@ -193,7 +197,8 @@ write_header (cipher_filter_context_t *cfx, iobuf_t a)
if (err)
goto leave;
log_printhex (cfx->dek->key, cfx->dek->keylen, "thekey:");
if (DBG_CRYPTO)
log_printhex (cfx->dek->key, cfx->dek->keylen, "thekey:");
err = gcry_cipher_setkey (cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen);
if (err)
return err;
@ -226,7 +231,6 @@ write_auth_tag (cipher_filter_context_t *cfx, iobuf_t a)
err = my_iobuf_write (a, tag, 16);
if (err)
goto leave;
log_printhex (tag, 16, "wrote tag:");
leave:
return err;
@ -272,7 +276,8 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
size_t n;
/* Put the data into a buffer, flush and encrypt as needed. */
log_debug ("flushing %zu bytes (cur buflen=%zu)\n", size, cfx->buflen);
if (DBG_FILTER)
log_debug ("flushing %zu bytes (cur buflen=%zu)\n", size, cfx->buflen);
do
{
if (cfx->buflen + size < cfx->bufsize)
@ -284,10 +289,11 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
{
size_t n1 = cfx->chunksize - cfx->chunklen;
newchunk = 1;
log_debug ("chunksize %ju reached;"
" cur buflen=%zu using %zu of %zu\n",
(uintmax_t)cfx->chunksize, (uintmax_t)cfx->buflen,
n1, n);
if (DBG_FILTER)
log_debug ("chunksize %ju reached;"
" cur buflen=%zu using %zu of %zu\n",
(uintmax_t)cfx->chunksize, (uintmax_t)cfx->buflen,
n1, n);
n = n1;
}
@ -298,11 +304,14 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
if (cfx->buflen == cfx->bufsize || newchunk)
{
log_debug ("encrypting: buflen=%zu %s %p\n",
cfx->buflen, newchunk?"(newchunk)":"", cfx->cipher_hd);
if (DBG_FILTER)
log_debug ("encrypting: buflen=%zu %s %p\n",
cfx->buflen, newchunk?"(newchunk)":"", cfx->cipher_hd);
if (newchunk)
gcry_cipher_final (cfx->cipher_hd);
if (newchunk)
if (!DBG_FILTER)
;
else if (newchunk)
log_printhex (cfx->buffer, cfx->buflen, "plain(1):");
else if (cfx->buflen > 32)
log_printhex (cfx->buffer + cfx->buflen - 32, 32,
@ -314,7 +323,7 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
* mode. */
gcry_cipher_encrypt (cfx->cipher_hd, cfx->buffer, cfx->buflen,
NULL, 0);
if (newchunk)
if (newchunk && DBG_FILTER)
log_printhex (cfx->buffer, cfx->buflen, "ciphr(1):");
err = my_iobuf_write (a, cfx->buffer, cfx->buflen);
if (err)
@ -325,18 +334,19 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
if (newchunk)
{
log_debug ("chunklen=%ju total=%ju\n",
(uintmax_t)cfx->chunklen, (uintmax_t)cfx->total);
if (DBG_FILTER)
log_debug ("chunklen=%ju total=%ju\n",
(uintmax_t)cfx->chunklen, (uintmax_t)cfx->total);
err = write_auth_tag (cfx, a);
if (err)
{
log_debug ("gcry_cipher_gettag failed: %s\n",
log_error ("gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
goto leave;
}
log_debug ("starting a new chunk (cur size=%zu)\n", size);
log_printhex (buf, size, "cur buf:");
if (DBG_FILTER)
log_debug ("starting a new chunk (cur size=%zu)\n", size);
cfx->chunkindex++;
cfx->chunklen = 0;
err = set_nonce (cfx);
@ -373,10 +383,10 @@ do_free (cipher_filter_context_t *cfx, iobuf_t a)
/* Encrypt any remaining bytes. */
if (cfx->buflen)
{
log_debug ("processing last %zu bytes of the last chunk\n", cfx->buflen);
log_printhex (cfx->buffer, cfx->buflen, "plain(2):");
if (DBG_FILTER)
log_debug ("processing last %zu bytes of the last chunk\n",
cfx->buflen);
gcry_cipher_encrypt (cfx->cipher_hd, cfx->buffer, cfx->buflen, NULL, 0);
log_printhex (cfx->buffer, cfx->buflen, "ciphr(2):");
err = my_iobuf_write (a, cfx->buffer, cfx->buflen);
if (err)
goto leave;
@ -386,14 +396,16 @@ do_free (cipher_filter_context_t *cfx, iobuf_t a)
}
/* Get and write the authentication tag. */
log_debug ("chunklen=%ju total=%ju\n",
(uintmax_t)cfx->chunklen, (uintmax_t)cfx->total);
if (DBG_FILTER)
log_debug ("chunklen=%ju total=%ju\n",
(uintmax_t)cfx->chunklen, (uintmax_t)cfx->total);
err = write_auth_tag (cfx, a);
if (err)
goto leave;
/* Write the final chunk. */
log_debug ("creating final chunk\n");
if (DBG_FILTER)
log_debug ("creating final chunk\n");
err = write_final_chunk (cfx, a);
leave:

View File

@ -150,7 +150,8 @@ aead_set_nonce (decode_filter_ctx_t dfx)
nonce[i++] ^= dfx->chunkindex >> 8;
nonce[i++] ^= dfx->chunkindex;
log_printhex (nonce, i, "nonce:");
if (DBG_CRYPTO)
log_printhex (nonce, i, "nonce:");
return gcry_cipher_setiv (dfx->cipher_hd, nonce, i);
}
@ -186,7 +187,8 @@ aead_set_ad (decode_filter_ctx_t dfx, int final)
ad[19] = dfx->total >> 8;
ad[20] = dfx->total;
}
log_printhex (ad, final? 21 : 13, "authdata:");
if (DBG_CRYPTO)
log_printhex (ad, final? 21 : 13, "authdata:");
return gcry_cipher_authenticate (dfx->cipher_hd, ad, final? 21 : 13);
}
@ -327,7 +329,8 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
if (rc)
goto leave; /* Should never happen. */
log_printhex (dek->key, dek->keylen, "thekey:");
if (DBG_CRYPTO)
log_printhex (dek->key, dek->keylen, "thekey:");
rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
{
@ -631,9 +634,10 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
dfx->eof_seen = 1; /* Normal EOF. */
}
log_debug ("decrypt: chunklen=%ju total=%ju size=%zu n=%zu%s\n",
(uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, n,
dfx->eof_seen? " eof":"");
if (DBG_FILTER)
log_debug ("decrypt: chunklen=%ju total=%ju size=%zu n=%zu%s\n",
(uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, n,
dfx->eof_seen? " eof":"");
/* Now decrypt the buffer. */
if (n && dfx->eof_seen > 1)
@ -653,12 +657,13 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
{
size_t n0 = dfx->chunksize - dfx->chunklen;
log_debug ("chunksize will be reached: n0=%zu\n", n0);
if (DBG_FILTER)
log_debug ("chunksize will be reached: n0=%zu\n", n0);
gcry_cipher_final (dfx->cipher_hd);
err = gcry_cipher_decrypt (dfx->cipher_hd, buf, n0, NULL, 0);
if (err)
{
log_debug ("gcry_cipher_decrypt failed (1): %s\n",
log_error ("gcry_cipher_decrypt failed (1): %s\n",
gpg_strerror (err));
goto leave;
}
@ -668,15 +673,18 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
off = n0;
n -= n0;
log_debug ("bytes left: %zu off=%zu\n", n, off);
if (DBG_FILTER)
log_debug ("bytes left: %zu off=%zu\n", n, off);
log_assert (n >= 16);
log_assert (dfx->defer_filled);
log_printhex (buf+off, 16, "tag:");
if (DBG_CRYPTO)
log_printhex (buf+off, 16, "tag:");
err = gcry_cipher_checktag (dfx->cipher_hd, buf + off, 16);
if (err)
{
log_debug ("gcry_cipher_checktag failed (1): %s\n",
gpg_strerror (err));
if (DBG_FILTER)
log_debug ("gcry_cipher_checktag failed (1): %s\n",
gpg_strerror (err));
/* Return Bad Signature like we do with MDC encryption. */
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = gpg_error (GPG_ERR_BAD_SIGNATURE);
@ -714,7 +722,8 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
err = gcry_cipher_decrypt (dfx->cipher_hd, buf + off, n, NULL, 0);
if (err)
{
log_debug ("gcry_cipher_decrypt failed (2): %s\n",gpg_strerror (err));
log_error ("gcry_cipher_decrypt failed (2): %s\n",
gpg_strerror (err));
goto leave;
}
dfx->chunklen += n;
@ -723,14 +732,15 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
if (dfx->eof_seen)
{
/* log_printhex (buf+off, n, "buf+off:"); */
log_debug ("eof seen: chunklen=%ju total=%ju off=%zu n=%zu\n",
(uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, off, n);
if (DBG_FILTER)
log_debug ("eof seen: chunklen=%ju total=%ju off=%zu n=%zu\n",
(uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, off, n);
log_assert (dfx->defer_filled);
err = gcry_cipher_checktag (dfx->cipher_hd, dfx->defer, 16);
if (err)
{
log_debug ("gcry_cipher_checktag failed (2): %s\n",
log_error ("gcry_cipher_checktag failed (2): %s\n",
gpg_strerror (err));
/* Return Bad Signature like we do with MDC encryption. */
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
@ -751,15 +761,16 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
err = gcry_cipher_decrypt (dfx->cipher_hd, buf, 0, NULL, 0);
if (err)
{
log_debug ("gcry_cipher_decrypt failed (final): %s\n",
log_error ("gcry_cipher_decrypt failed (final): %s\n",
gpg_strerror (err));
goto leave;
}
err = gcry_cipher_checktag (dfx->cipher_hd, dfx->defer+16, 16);
if (err)
{
log_debug ("gcry_cipher_checktag failed (final): %s\n",
gpg_strerror (err));
if (DBG_FILTER)
log_debug ("gcry_cipher_checktag failed (final): %s\n",
gpg_strerror (err));
/* Return Bad Signature like we do with MDC encryption. */
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = gpg_error (GPG_ERR_BAD_SIGNATURE);
@ -767,7 +778,8 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
}
n += off;
log_debug ("eof seen: returning %zu\n", n);
if (DBG_FILTER)
log_debug ("eof seen: returning %zu\n", n);
/* log_printhex (buf, n, "buf:"); */
}
else

View File

@ -105,6 +105,7 @@ enum cmd_and_opt_values
oBatch = 500,
oMaxOutput,
oInputSizeHint,
oChunkSize,
oSigNotation,
oCertNotation,
oShowNotation,
@ -596,6 +597,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
ARGPARSE_p_u (oMaxOutput, "max-output", "@"),
ARGPARSE_s_s (oInputSizeHint, "input-size-hint", "@"),
ARGPARSE_s_i (oChunkSize, "chunk-size", "@"),
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
ARGPARSE_s_n (oQuiet, "quiet", "@"),
@ -1015,6 +1017,18 @@ build_list_cipher_algo_name (int algo)
return openpgp_cipher_algo_name (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)
{
@ -1036,7 +1050,7 @@ build_list_md_algo_name (int algo)
static const char *
my_strusage( int level )
{
static char *digests, *pubkeys, *ciphers, *zips, *ver_gcry;
static char *digests, *pubkeys, *ciphers, *zips, *aeads, *ver_gcry;
const char *p;
switch( level ) {
@ -1096,13 +1110,20 @@ my_strusage( int level )
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',
build_list_md_algo_name,
build_list_md_test_algo );
p = digests;
break;
case 37:
case 38:
if( !zips )
zips = build_list(_("Compression: "),'Z',
compress_algo_to_string,
@ -1123,6 +1144,7 @@ build_list (const char *text, char letter,
membuf_t mb;
int indent;
int i, j, len;
int limit;
const char *s;
char *string;
@ -1133,7 +1155,8 @@ build_list (const char *text, char letter,
len = 0;
init_membuf (&mb, 512);
for (i=0; i <= 110; i++ )
limit = (letter == 'A')? 4 : 110;
for (i=0; i <= limit; i++ )
{
if (!chkf (i) && (s = mapf (i)))
{
@ -2648,6 +2671,10 @@ main (int argc, char **argv)
opt.input_size_hint = string_to_u64 (pargs.r.ret_str);
break;
case oChunkSize:
opt.chunk_size = pargs.r.ret_int;
break;
case oQuiet: opt.quiet = 1; break;
case oNoTTY: tty_no_terminal(1); break;
case oDryRun: opt.dry_run = 1; break;
@ -3836,6 +3863,21 @@ main (int argc, char **argv)
keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP))
log_error(_("invalid personal compress preferences\n"));
/* Check chunk size. Please fix also the man page if you chnage
* the default. The limits are given by the specs. */
if (!opt.chunk_size)
opt.chunk_size = 30; /* Default to 1 GiB chunks. */
else if (opt.chunk_size < 6)
{
opt.chunk_size = 6;
log_info (_("chunk size invalid - using %d\n"), opt.chunk_size);
}
else if (opt.chunk_size > 62)
{
opt.chunk_size = 62;
log_info (_("chunk size invalid - using %d\n"), opt.chunk_size);
}
/* We don't support all possible commands with multifile yet */
if(multifile)
{

View File

@ -41,7 +41,11 @@
# define DEFAULT_CIPHER_ALGO CIPHER_ALGO_3DES
#endif
#define DEFAULT_AEAD_ALGO AEAD_ALGO_EAX
#if GCRYPT_VERSION_NUMBER < 0x019000
# define DEFAULT_AEAD_ALGO AEAD_ALGO_OCB
#else
# define DEFAULT_AEAD_ALGO AEAD_ALGO_EAX
#endif
#define DEFAULT_DIGEST_ALGO ((GNUPG)? DIGEST_ALGO_SHA256:DIGEST_ALGO_SHA1)
#define DEFAULT_S2K_DIGEST_ALGO DIGEST_ALGO_SHA1

View File

@ -591,11 +591,23 @@ openpgp_cipher_algo_name (cipher_algo_t algo)
gpg_error_t
openpgp_aead_test_algo (aead_algo_t algo)
{
/* FIXME: We currently have no easy way to test whether libgcrypt
* implements a mode. The only way we can do this is to open a
* cipher context with that mode and close it immediately. That is
* a bit costly. So we look at the libgcrypt version and assume
* nothing has been patched out. */
switch (algo)
{
case AEAD_ALGO_NONE:
break;
case AEAD_ALGO_EAX:
#if GCRYPT_VERSION_NUMBER < 0x010900
break;
#else
return 0;
#endif
case AEAD_ALGO_OCB:
return 0;
}

View File

@ -62,6 +62,9 @@ struct
* progress info and to decide on how to allocate buffers. */
uint64_t input_size_hint;
/* The AEAD chunk size expressed as a power of 2. */
int chunk_size;
int dry_run;
int autostart;
int list_only;
@ -319,7 +322,6 @@ struct {
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#define DBG_IPC (opt.debug & DBG_IPC_VALUE)
#define DBG_IPC (opt.debug & DBG_IPC_VALUE)
#define DBG_CLOCK (opt.debug & DBG_CLOCK_VALUE)
#define DBG_LOOKUP (opt.debug & DBG_LOOKUP_VALUE)
#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE)