[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