[git] GnuPG - branch, master, updated. gnupg-2.2.5-111-g618b863

by Werner Koch cvs at cvs.gnupg.org
Tue Feb 27 21:17:50 CET 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  618b86325f776f7250ad2bb09680e4bb427d7e50 (commit)
       via  ad989373f1a46139ed0fbc4d4a91069b78617ad9 (commit)
      from  b703ba725dadca8298a0c69365225f9a7ff60ae2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 618b86325f776f7250ad2bb09680e4bb427d7e50
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Feb 27 21:11:20 2018 +0100

    gpg: Simplify the AEAD decryption function.
    
    * g10/decrypt-data.c (aead_set_nonce, aead_set_ad): Merge into ...
    (aead_set_nonce_and_ad): new single function.  Change callers.
    (decrypt_data): Do not set the nonce and ad here.
    (aead_underflow): Get rid of the LAST_CHUNK_DONE hack.
    --
    
    The main change here is that we now re-init the context only right
    before we decrypt and not after a checktag.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index b00f2bc..5594d90 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -117,11 +117,15 @@ release_dfx_context (decode_filter_ctx_t dfx)
 }
 
 
-/* Set the nonce for AEAD.  This also reset the decryption machinery
- * so that the handle can be used for a new chunk.  */
+/* Set the nonce and the additional data for the current chunk.  This
+ * also reset the decryption machinery * so that the handle can be
+ * used for a new chunk.  If FINAL is set the final AEAD chunk is
+ * processed.  */
 static gpg_error_t
-aead_set_nonce (decode_filter_ctx_t dfx)
+aead_set_nonce_and_ad (decode_filter_ctx_t dfx, int final)
 {
+  gpg_error_t err;
+  unsigned char ad[21];
   unsigned char nonce[16];
   int i;
 
@@ -151,16 +155,9 @@ aead_set_nonce (decode_filter_ctx_t dfx)
 
   if (DBG_CRYPTO)
     log_printhex (nonce, i, "nonce:");
-  return gcry_cipher_setiv (dfx->cipher_hd, nonce, i);
-}
-
-
-/* Set the additional data for the current chunk.  If FINAL is set the
- * final AEAD chunk is processed.  */
-static gpg_error_t
-aead_set_ad (decode_filter_ctx_t dfx, int final)
-{
-  unsigned char ad[21];
+  err = gcry_cipher_setiv (dfx->cipher_hd, nonce, i);
+  if (err)
+    return err;
 
   ad[0] = (0xc0 | PKT_ENCRYPTED_AEAD);
   ad[1] = 1;
@@ -371,14 +368,6 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
           goto leave;
         }
 
-      rc = aead_set_nonce (dfx);
-      if (rc)
-        goto leave;
-
-      rc = aead_set_ad (dfx, 0);
-      if (rc)
-        goto leave;
-
     }
   else /* CFB encryption.  */
     {
@@ -606,7 +595,6 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
   size_t totallen = 0; /* The number of bytes to return on success or EOF.  */
   size_t off = 0;      /* The offset into the buffer.  */
   size_t len;          /* The current number of bytes in BUF+OFF.  */
-  int last_chunk_done = 0; /* Flag that we processed the last chunk.  */
 
   log_assert (size > 48); /* Our code requires at least this size.  */
 
@@ -655,10 +643,10 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
     }
   /* log_printhex (dfx->holdback, dfx->holdbacklen, "holdback:"); */
 
-  /* Decrypt the buffer.  This requires a loop because a chunk may end
-   * within the buffer.  */
+  /* Decrypt the buffer.  This first requires a loop to handle the
+   * case when a chunk ends within the buffer.  */
   if (DBG_FILTER)
-    log_debug ("decrypt loop: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
+    log_debug ("decrypt: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
                (uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, len,
                dfx->eof_seen? " eof":"");
 
@@ -669,6 +657,15 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
 
       if (DBG_FILTER)
         log_debug ("chunksize will be reached: n=%zu\n", n);
+
+      if (!dfx->chunklen)
+        {
+          /* First data for this chunk - prepare.  */
+          err = aead_set_nonce_and_ad (dfx, 0);
+          if (err)
+            goto leave;
+        }
+
       /* log_printhex (buf, n, "ciph:"); */
       gcry_cipher_final (dfx->cipher_hd);
       err = gcry_cipher_decrypt (dfx->cipher_hd, buf+off, n, NULL, 0);
@@ -710,7 +707,6 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
                   err = gpg_error (GPG_ERR_TRUNCATED);
                   goto leave;
                 }
-              last_chunk_done = 1;
             }
           else
             {
@@ -735,25 +731,23 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
       err = aead_checktag (dfx, 0, tagbuf);
       if (err)
         goto leave;
+      dfx->chunklen = 0;
+      dfx->chunkindex++;
 
-      /* Prepare a new chunk.  */
-      if (!last_chunk_done)
+      continue;
+    }
+
+  /* The bulk decryption of our buffer.  */
+  if (len)
+    {
+      if (!dfx->chunklen)
         {
-          dfx->chunklen = 0;
-          dfx->chunkindex++;
-          err = aead_set_nonce (dfx);
-          if (err)
-            goto leave;
-          err = aead_set_ad (dfx, 0);
+          /* First data for this chunk - prepare.  */
+          err = aead_set_nonce_and_ad (dfx, 0);
           if (err)
             goto leave;
         }
 
-      continue;
-    }
-
-  if (!last_chunk_done)
-    {
       if (dfx->eof_seen)
         {
           /* This is the last block of the last chunk.  Its length may
@@ -777,28 +771,24 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
   if (dfx->eof_seen)
     {
       if (DBG_FILTER)
-        log_debug ("eof seen: holdback buffer has the %s.\n",
-                   last_chunk_done? "final tag":"last and final tag");
+        log_debug ("eof seen: holdback buffer has the last and final tag\n");
 
-      if (!last_chunk_done)
+      log_assert (dfx->holdbacklen >= 32);
+      if (dfx->chunklen)
         {
-          log_assert (dfx->holdbacklen >= 32);
           err = aead_checktag (dfx, 0, dfx->holdback);
           if (err)
             goto leave;
+          dfx->chunklen = 0;
+          dfx->chunkindex++;
         }
 
       /* Check the final chunk.  */
-      if (dfx->chunklen)
-        dfx->chunkindex++;
-      err = aead_set_nonce (dfx);
-      if (err)
-        goto leave;
-      err = aead_set_ad (dfx, 1);
+      err = aead_set_nonce_and_ad (dfx, 1);
       if (err)
         goto leave;
       gcry_cipher_final (dfx->cipher_hd);
-      /* Decrypt an empty string.  */
+      /* Decrypt an empty string (using HOLDBACK as a dummy).  */
       err = gcry_cipher_decrypt (dfx->cipher_hd, dfx->holdback, 0, NULL, 0);
       if (err)
         {
@@ -806,7 +796,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
                      gpg_strerror (err));
           goto leave;
         }
-      err = aead_checktag (dfx, 1, dfx->holdback+(last_chunk_done?0:16));
+      err = aead_checktag (dfx, 1, dfx->holdback+16);
       if (err)
         goto leave;
       err = gpg_error (GPG_ERR_EOF);

commit ad989373f1a46139ed0fbc4d4a91069b78617ad9
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Feb 27 19:50:54 2018 +0100

    gpg: Factor common code out of the AEAD decryption function.
    
    * g10/decrypt-data.c (aead_underflow): Factor reading and checking
    code code out to ...
    (fill_buffer, aead_checktag): new functions.
    --
    
    Here is a simple test script to check against a set of encrypted files
    with naming convention like "symenc-aead-eax-c6-56.asc"
    
    # ------------------------ >8 ------------------------
    set -e
    GPG=../g10/gpg
    for file in "$@"; do
      echo "${file##*/}" | ( IFS=- read dummy1 dummy2 mode cbyte len rest
      len="${len%.*}"
      cbyte="${cbyte#c}"
      [ "$dummy1" != "symenc" -o "$dummy2" != "aead" ] && continue
      echo "checking mode=$mode chunkbyte=$cbyte length=$len"
      if ! $GPG --no-options --rfc4880bis --batch --passphrase "abc" \
                 -d < $file >tmp.plain 2>/dev/null; then
          echo "Decryption failed for $file" >&2
          exit 2
      fi
      plainlen=$(wc -c <tmp.plain)
      if [ $plainlen -ne $len ]; then
          echo "Plaintext length mismatch for $file (want=$len have=$plainlen)" >&2
          exit 2
      fi
    
      )
    done
    echo "all files are okay" >&2
    # ------------------------ 8< ------------------------
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index 0b0051a..b00f2bc 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -192,6 +192,28 @@ aead_set_ad (decode_filter_ctx_t dfx, int final)
 }
 
 
+/* Helper to check the 16 byte tag in TAGBUF.  The FINAL flag is only
+ * for debug messages.  */
+static gpg_error_t
+aead_checktag (decode_filter_ctx_t dfx, int final, const void *tagbuf)
+{
+  gpg_error_t err;
+
+  if (DBG_FILTER)
+    log_printhex (tagbuf, 16, "tag:");
+  err = gcry_cipher_checktag (dfx->cipher_hd, tagbuf, 16);
+  if (err)
+    {
+      log_error ("gcry_cipher_checktag%s failed: %s\n",
+                 final? " (final)":"", gpg_strerror (err));
+      return err;
+    }
+  if (DBG_FILTER)
+    log_debug ("%stag is valid\n", final?"final ":"");
+  return 0;
+}
+
+
 /****************
  * Decrypt the data, specified by ED with the key DEK.
  */
@@ -531,6 +553,49 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
 }
 
 
+/* Fill BUFFER with up to NBYTES-OFFSET from STREAM utilizing
+ * information from the context DFX.  Returns the new offset which is
+ * the number of bytes read plus the original offset.  On EOF the
+ * respective flag in DFX is set. */
+static size_t
+fill_buffer (decode_filter_ctx_t dfx, iobuf_t stream,
+             byte *buffer, size_t nbytes, size_t offset)
+{
+  size_t nread = offset;
+  int c;
+
+  if (dfx->partial)
+    {
+      for (; nread < nbytes; nread++ )
+        {
+          if ((c = iobuf_get (stream)) == -1)
+            {
+              dfx->eof_seen = 1; /* Normal EOF. */
+              break;
+            }
+          buffer[nread] = c;
+        }
+    }
+  else
+    {
+      for (; nread < nbytes && dfx->length; nread++, dfx->length--)
+        {
+          c = iobuf_get (stream);
+          if (c == -1)
+            {
+              dfx->eof_seen = 3; /* Premature EOF. */
+              break;
+            }
+          buffer[nread] = c;
+        }
+      if (!dfx->length)
+        dfx->eof_seen = 1; /* Normal EOF.  */
+    }
+
+  return nread;
+}
+
+
 /* The core of the AEAD decryption.  This is the underflow function of
  * the aead_decode_filter.  */
 static gpg_error_t
@@ -542,7 +607,6 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
   size_t off = 0;      /* The offset into the buffer.  */
   size_t len;          /* The current number of bytes in BUF+OFF.  */
   int last_chunk_done = 0; /* Flag that we processed the last chunk.  */
-  int c;
 
   log_assert (size > 48); /* Our code requires at least this size.  */
 
@@ -560,39 +624,12 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
    * chunksize.  After the last data byte from the last chunk 32 more
    * bytes are expected for the last chunk's tag and the following
    * final chunk's tag.  To detect the EOF we need to try reading at least
-   * one further byte; however we try to ready 16 extra bytes to avoid
+   * one further byte; however we try to read 16 extra bytes to avoid
    * single byte reads in some lower layers.  The outcome is that we
    * have up to 48 extra extra octets which we will later put into the
    * holdback buffer for the next invocation (which handles the EOF
    * case).  */
-  if (dfx->partial)
-    {
-      for (; len < size; len++ )
-        {
-          if ((c = iobuf_get (a)) == -1)
-            {
-              dfx->eof_seen = 1; /* Normal EOF. */
-              break;
-            }
-          buf[len] = c;
-        }
-    }
-  else
-    {
-      for (; len < size && dfx->length; len++, dfx->length--)
-        {
-          c = iobuf_get (a);
-          if (c == -1)
-            {
-              dfx->eof_seen = 3; /* Premature EOF. */
-              break;
-            }
-          buf[len] = c;
-        }
-      if (!dfx->length)
-        dfx->eof_seen = 1; /* Normal EOF.  */
-    }
-
+  len = fill_buffer (dfx, a, buf, size, len);
   if (len < 32)
     {
       /* Not enough data for the last two tags.  */
@@ -673,47 +710,19 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
                   err = gpg_error (GPG_ERR_TRUNCATED);
                   goto leave;
                 }
-              len = 0;
               last_chunk_done = 1;
             }
           else
             {
-              len = dfx->holdbacklen;
-              if (dfx->partial)
-                {
-                  for (; len < 48; len++ )
-                    {
-                      if ((c = iobuf_get (a)) == -1)
-                        {
-                          dfx->eof_seen = 1; /* Normal EOF. */
-                          break;
-                        }
-                      dfx->holdback[len] = c;
-                    }
-                }
-              else
-                {
-                  for (; len < 48 && dfx->length; len++, dfx->length--)
-                    {
-                      c = iobuf_get (a);
-                      if (c == -1)
-                        {
-                          dfx->eof_seen = 3; /* Premature EOF. */
-                          break;
-                        }
-                      dfx->holdback[len] = c;
-                    }
-                  if (!dfx->length)
-                    dfx->eof_seen = 1; /* Normal EOF.  */
-                }
-              if (len < 32)
+              len = 0;
+              dfx->holdbacklen = fill_buffer (dfx, a, dfx->holdback, 48,
+                                              dfx->holdbacklen);
+              if (dfx->holdbacklen < 32)
                 {
                   /* Not enough data for the last two tags.  */
                   err = gpg_error (GPG_ERR_TRUNCATED);
                   goto leave;
                 }
-              dfx->holdbacklen = len;
-              len = 0;
             }
         }
       else /* We already have the full tag.  */
@@ -723,18 +732,9 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
           memmove (buf + off, buf + off + 16, len - 16);
           len -= 16;
         }
-      if (DBG_CRYPTO)
-        log_printhex (tagbuf, 16, "tag:");
-      err = gcry_cipher_checktag (dfx->cipher_hd, tagbuf, 16);
+      err = aead_checktag (dfx, 0, tagbuf);
       if (err)
-        {
-          if (DBG_FILTER)
-            log_debug ("gcry_cipher_checktag failed (1): %s\n",
-                       gpg_strerror (err));
-          goto leave;
-        }
-      if (DBG_FILTER)
-        log_debug ("tag is valid\n");
+        goto leave;
 
       /* Prepare a new chunk.  */
       if (!last_chunk_done)
@@ -783,18 +783,9 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
       if (!last_chunk_done)
         {
           log_assert (dfx->holdbacklen >= 32);
-
-          if (DBG_FILTER)
-            log_printhex (dfx->holdback, 16, "tag:");
-          err = gcry_cipher_checktag (dfx->cipher_hd, dfx->holdback, 16);
+          err = aead_checktag (dfx, 0, dfx->holdback);
           if (err)
-            {
-              log_error ("gcry_cipher_checktag failed (2): %s\n",
-                         gpg_strerror (err));
-              goto leave;
-            }
-          if (DBG_FILTER)
-            log_debug ("tag is valid\n");
+            goto leave;
         }
 
       /* Check the final chunk.  */
@@ -815,19 +806,9 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
                      gpg_strerror (err));
           goto leave;
         }
-      if (DBG_CRYPTO)
-        log_printhex (dfx->holdback+(last_chunk_done?0:16), 16, "tag:");
-      err = gcry_cipher_checktag (dfx->cipher_hd,
-                                  dfx->holdback+(last_chunk_done?0:16), 16);
+      err = aead_checktag (dfx, 1, dfx->holdback+(last_chunk_done?0:16));
       if (err)
-        {
-          if (DBG_FILTER)
-            log_debug ("gcry_cipher_checktag failed (final): %s\n",
-                       gpg_strerror (err));
-          goto leave;
-        }
-      if (DBG_FILTER)
-        log_debug ("final tag is valid\n");
+        goto leave;
       err = gpg_error (GPG_ERR_EOF);
     }
 

-----------------------------------------------------------------------

Summary of changes:
 g10/decrypt-data.c | 263 ++++++++++++++++++++++++-----------------------------
 1 file changed, 117 insertions(+), 146 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list