[PATCH] Implement CFB with 8bit mode

Mathias L. Baumann mathias.baumann at sociomantic.com
Mon Jan 30 14:47:13 CET 2017


* cipher/cipher-cfb.c: add 8bit variants of decrypt/encrypt functions
* tests/basic.c: add tests for cfb8 with AES and 3DES
* adjust code flow to work with constant GCRY_CIPHER_MODE_CFB8

Signed-off-by: Mathias L. Baumann <mathias.baumann at sociomantic.com>

---
 cipher/cipher-cfb.c      | 86 ++++++++++++++++++++++++++++++++++++++++++++
 cipher/cipher-internal.h |  8 +++++
 cipher/cipher.c          |  9 +++++
 tests/basic.c            | 93
+++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 195 insertions(+), 1 deletion(-)

diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c
index f289ed38..dee4a1cb 100644
--- a/cipher/cipher-cfb.c
+++ b/cipher/cipher-cfb.c
@@ -223,3 +223,89 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,

   return 0;
 }
+
+
+gcry_err_code_t
+_gcry_cipher_cfb8_encrypt (gcry_cipher_hd_t c,
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
+{
+  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
+  size_t blocksize = c->spec->blocksize;
+  unsigned int burn, nburn;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  burn = 0;
+
+  while ( inbuflen > 0)
+    {
+      /* Encrypt the IV. */
+      nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
+
+      outbuf[0] = c->lastiv[0] ^ inbuf[0];
+
+      /* Bitshift iv by 8 bit to the left */
+      for (int i = 0; i < blocksize-1; i++)
+        c->u_iv.iv[i] = c->u_iv.iv[i+1];
+
+      /* append cipher text to iv */
+      c->u_iv.iv[blocksize-1] = outbuf[0];
+
+      outbuf += 1;
+      inbuf += 1;
+      inbuflen -= 1;
+    }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_cfb8_decrypt (gcry_cipher_hd_t c,
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
+{
+  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
+  size_t blocksize = c->spec->blocksize;
+  unsigned int burn, nburn;
+  unsigned char appendee;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  burn = 0;
+
+  while (inbuflen > 0)
+    {
+      /* Encrypt the IV. */
+      nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv );
+      burn = nburn > burn ? nburn : burn;
+
+      /* inbuf might == outbuf, make sure we keep the value
+         so we can append it later */
+      appendee = inbuf[0];
+
+      outbuf[0] = inbuf[0] ^ c->lastiv[0];
+
+      /* Bitshift iv by 8 bit to the left */
+      for (int i = 0; i < blocksize-1; i++)
+        c->u_iv.iv[i] = c->u_iv.iv[i+1];
+
+      c->u_iv.iv[blocksize-1] = appendee;
+
+      outbuf += 1;
+      inbuf += 1;
+      inbuflen -= 1;
+    }
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
+  return 0;
+}
diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h
index 33d0629c..ea9c33d3 100644
--- a/cipher/cipher-internal.h
+++ b/cipher/cipher-internal.h
@@ -348,6 +348,14 @@ gcry_err_code_t _gcry_cipher_cfb_decrypt
 /*           */ (gcry_cipher_hd_t c,
                  unsigned char *outbuf, size_t outbuflen,
                  const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_cfb8_encrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_cfb8_decrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);


 /*-- cipher-ofb.c --*/
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 06ce1dad..124700e9 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -415,6 +415,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
       case GCRY_CIPHER_MODE_ECB:
       case GCRY_CIPHER_MODE_CBC:
       case GCRY_CIPHER_MODE_CFB:
+      case GCRY_CIPHER_MODE_CFB8:
       case GCRY_CIPHER_MODE_OFB:
       case GCRY_CIPHER_MODE_CTR:
       case GCRY_CIPHER_MODE_AESWRAP:
@@ -902,6 +903,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf,
size_t outbuflen,
       rc = _gcry_cipher_cfb_encrypt (c, outbuf, outbuflen, inbuf,
inbuflen);
       break;

+    case GCRY_CIPHER_MODE_CFB8:
+      rc = _gcry_cipher_cfb8_encrypt (c, outbuf, outbuflen, inbuf,
inbuflen);
+      break;
+
     case GCRY_CIPHER_MODE_OFB:
       rc = _gcry_cipher_ofb_encrypt (c, outbuf, outbuflen, inbuf,
inbuflen);
       break;
@@ -1029,6 +1034,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf,
size_t outbuflen,
       rc = _gcry_cipher_cfb_decrypt (c, outbuf, outbuflen, inbuf,
inbuflen);
       break;

+    case GCRY_CIPHER_MODE_CFB8:
+      rc = _gcry_cipher_cfb8_decrypt (c, outbuf, outbuflen, inbuf,
inbuflen);
+      break;
+
     case GCRY_CIPHER_MODE_OFB:
       rc = _gcry_cipher_ofb_encrypt (c, outbuf, outbuflen, inbuf,
inbuflen);
       break;
diff --git a/tests/basic.c b/tests/basic.c
index 6d086b55..8b17bf75 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -893,7 +893,98 @@ check_cfb_cipher (void)
             16,

"\x75\xa3\x85\x74\x1a\xb9\xce\xf8\x20\x31\x62\x3d\x55\xb1\xe4\x71" }
         }
-      }
+      },
+      { GCRY_CIPHER_AES, 1,
+        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\x6b",
+            1,
+            "\x3b"},
+          { "\xc1",
+            1,
+            "\x79"},
+          { "\xbe",
+            1,
+            "\x42"},
+          { "\xe2",
+            1,
+            "\x4c"},
+        }
+      },
+      { GCRY_CIPHER_AES192, 1,
+
"\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\x6b",
+            1,
+            "\xcd"},
+          { "\xc1",
+            1,
+            "\xa2"},
+          { "\xbe",
+            1,
+            "\x52"},
+          { "\xe2",
+            1,
+            "\x1e"},
+        }
+      },
+      { GCRY_CIPHER_AES256, 1,
+
"\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\x6b",
+            1,
+            "\xdc"},
+          { "\xc1",
+            1,
+            "\x1f"},
+          { "\xbe",
+            1,
+            "\x1a"},
+          { "\xe2",
+            1,
+            "\x85"},
+        }
+      },
+      { GCRY_CIPHER_AES, 1,
+        "\x3a\x6f\x91\x59\x26\x3f\xa6\xce\xf2\xa0\x75\xca\xfa\xce\x58\x17",
+        "\x0f\xc2\x36\x62\xb7\xdb\xf7\x38\x27\xf0\xc7\xde\x32\x1c\xa3\x6e",
+        { { "\x87\xef\xeb\x8d\x55\x9e\xd3\x36\x77\x28",
+            10,
+            "\x8e\x9c\x50\x42\x56\x14\xd5\x40\xce\x11"},
+        }
+      },
+      { GCRY_CIPHER_AES192, 1,
+
"\x53\x7e\x7b\xf6\x61\xfd\x40\x24\xa0\x24\x61\x3f\x15\xb1\x36\x90\xf7\xd0\xc8\x47\xc1\xe1\x89\x65",
+        "\x3a\x81\xf9\xd9\xd3\xc1\x55\xb0\xca\xad\x5d\x73\x34\x94\x76\xfc",
+        { { "\xd3\xd8\xb9\xb9\x84\xad\xc2\x42\x37\xee",
+            10,
+            "\x38\x79\xfe\xa7\x2a\xc9\x99\x29\xe5\x3a"},
+        }
+      },
+      { GCRY_CIPHER_AES256, 1,
+
"\xeb\xbb\x45\x66\xb5\xe1\x82\xe0\xf0\x72\x46\x6b\x0b\x31\x1d\xf3\x8f\x91\x75\xbc\x02\x13\xa5\x53\x0b\xce\x2e\xc4\xd7\x4f\x40\x0d",
+        "\x09\x56\xa4\x8e\x01\x00\x2c\x9e\x16\x37\x6d\x6e\x30\x8d\xba\xd1",
+        { { "\xb0\xfe\x25\xac\x8d\x3d\x28\xa2\xf4\x71",
+            10,
+            "\x63\x8c\x68\x23\xe7\x25\x6f\xb5\x62\x6e"},
+        }
+      },
+      { GCRY_CIPHER_3DES, 1,
+
"\xe3\x34\x7a\x6b\x0b\xc1\x15\x2c\x64\x2a\x25\xcb\xd3\xbc\x31\xab\xfb\xa1\x62\xa8\x1f\x19\x7c\x15",
+        "\xb7\x40\xcc\x21\xe9\x25\xe3\xc8",
+        { { "\xdb\xe9\x15\xfc\xb3\x3b\xca\x18\xef\x14",
+            10,
+            "\xf4\x80\x1a\x8d\x03\x9d\xb4\xca\x8f\xf6"},
+        }
+      },
+      { GCRY_CIPHER_3DES, 1,
+
"\x7c\xa2\x89\x38\xba\x6b\xec\x1f\xfe\xc7\x8f\x7c\xd6\x97\x61\x94\x7c\xa2\x89\x38\xba\x6b\xec\x1f",
+        "\x95\x38\x96\x58\x6e\x49\xd3\x8f",
+        { { "\x2e\xa9\x56\xd4\xa2\x11\xdb\x68\x59\xb7",
+            10,
+            "\xf2\x0e\x53\x66\x74\xa6\x6f\xa7\x38\x05"},
+        }
+      },
     };
   gcry_cipher_hd_t hde, hdd;
   unsigned char out[MAX_DATA_LEN];
-- 
2.11.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0xDF9A49AD.asc
Type: application/pgp-keys
Size: 3144 bytes
Desc: not available
URL: </pipermail/attachments/20170130/8411eed1/attachment-0001.key>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: </pipermail/attachments/20170130/8411eed1/attachment-0001.sig>


More information about the Gcrypt-devel mailing list