diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/cipher-aead.c | 66 | ||||
-rw-r--r-- | g10/decrypt-data.c | 52 | ||||
-rw-r--r-- | g10/gpg.c | 48 | ||||
-rw-r--r-- | g10/main.h | 6 | ||||
-rw-r--r-- | g10/misc.c | 12 | ||||
-rw-r--r-- | g10/options.h | 4 |
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 @@ -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) |