aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/cipher-aead.c66
-rw-r--r--g10/decrypt-data.c52
-rw-r--r--g10/gpg.c48
-rw-r--r--g10/main.h6
-rw-r--r--g10/misc.c12
-rw-r--r--g10/options.h4
6 files changed, 136 insertions, 52 deletions
diff --git a/g10/cipher-aead.c b/g10/cipher-aead.c
index 637bd71a7..9cb57bdc6 100644
--- a/g10/cipher-aead.c
+++ b/g10/cipher-aead.c
@@ -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:
diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index 46650f269..3d7d74714 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -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
diff --git a/g10/gpg.c b/g10/gpg.c
index 2ae3e8aa0..283de2038 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -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", "@"),
@@ -1016,6 +1018,18 @@ build_list_cipher_algo_name (int 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)
{
/* By default we do not accept MD5 based signatures. To avoid
@@ -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)
{
diff --git a/g10/main.h b/g10/main.h
index a02c5740f..2f7c159a9 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -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
diff --git a/g10/misc.c b/g10/misc.c
index 36d3bdc36..8c54793ed 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -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;
}
diff --git a/g10/options.h b/g10/options.h
index 36bea694d..471aee7f4 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -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)