Add Propagating CBC (PCBC) mode
authorAndrey Rys <rys@lynxlynx.ru>
Sun, 28 Aug 2022 13:20:36 +0000 (15:20 +0200)
committerAndrey Rys <rys@lynxlynx.ru>
Sun, 28 Aug 2022 13:20:36 +0000 (15:20 +0200)
VERSION
tfc_bench.c
tfc_conf.c
tfc_misc.c
tfcrypt.c
tfcrypt.h
tfdef.h
tfpcbc.c [new file with mode: 0644]

diff --git a/VERSION b/VERSION
index 69a893aa31141827125ddaaee26966b7aed3de74..3fdcd7c44cb1791f45e7386a8f230e018fd7e052 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-66
+67
index 2c0553890101b5f6113631cc9205c999a83ccf85..e05ac78b3af805306b020f756cf81293f2258a22 100644 (file)
@@ -79,6 +79,10 @@ void do_benchmark(tfc_useconds useconds, double dseconds)
                        tf_cbc_encrypt(key, ctr, srcblk, srcblk, lblock);
                else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT)
                        tf_cbc_decrypt(key, ctr, srcblk, srcblk, lblock);
+               else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_ENCRYPT)
+                       tf_pcbc_encrypt(key, ctr, srcblk, srcblk, lblock);
+               else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_DECRYPT)
+                       tf_pcbc_decrypt(key, ctr, srcblk, srcblk, lblock);
 
                delta_processed += lblock;
        }
index fc9bec78d447bdaf47eec64bdc1bd38bb1f80042..fe36a13eaf90d4f1740dc16979159f3595595cac 100644 (file)
@@ -76,6 +76,8 @@ _nspc:
                                ctr_mode = TFC_MODE_STREAM;
                        else if (!strcasecmp(d, "cbc"))
                                ctr_mode = TFC_MODE_CBC;
+                       else if (!strcasecmp(d, "pcbc"))
+                               ctr_mode = TFC_MODE_PCBC;
                        else if (!strcasecmp(d, "ecb"))
                                ctr_mode = TFC_MODE_ECB;
                        else if (!strcasecmp(d, "xts"))
index 01998f2f13a877e451fd007cfac347282a2c896d..5902896e82c5b5b2352cfd2b7d75a580b3b2ec3d 100644 (file)
@@ -97,6 +97,7 @@ const char *tfc_modename(int mode)
                case TFC_MODE_XTS: return "XTS";
                case TFC_MODE_ECB: return "ECB";
                case TFC_MODE_CBC: return "CBC";
+               case TFC_MODE_PCBC: return "PCBC";
        }
 
        return NULL;
index cb126ae6d37a6b884fe4ca2a3ad536f1988eb72a..45438cb2bde7dc46cdc05ea0fba5b20d7ca7eebf 100644 (file)
--- a/tfcrypt.c
+++ b/tfcrypt.c
@@ -209,6 +209,8 @@ _baddfname:
                                        ctr_mode = TFC_MODE_STREAM;
                                else if (!strcasecmp(optarg, "cbc"))
                                        ctr_mode = TFC_MODE_CBC;
+                               else if (!strcasecmp(optarg, "pcbc"))
+                                       ctr_mode = TFC_MODE_PCBC;
                                else if (!strcasecmp(optarg, "ecb"))
                                        ctr_mode = TFC_MODE_ECB;
                                else if (!strcasecmp(optarg, "xts"))
@@ -1246,6 +1248,10 @@ _ragain: lio = xread(sfd, pblk, lrem);
                        tf_cbc_encrypt(key, ctr, dstblk, srcblk, ldone);
                else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT)
                        tf_cbc_decrypt(key, ctr, dstblk, srcblk, ldone);
+               else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_ENCRYPT)
+                       tf_pcbc_encrypt(key, ctr, dstblk, srcblk, ldone);
+               else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_DECRYPT)
+                       tf_pcbc_decrypt(key, ctr, dstblk, srcblk, ldone);
 
                else if (ctr_mode == TFC_MODE_PLAIN)
                        memcpy(dstblk, srcblk, ldone);
@@ -1340,6 +1346,7 @@ _macragain:               lio = xread(sfd, pblk, lrem);
                else if (ctr_mode == TFC_MODE_XTS) tf_xts_decrypt(key, xtskey, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits), xtsblocks);
                else if (ctr_mode == TFC_MODE_ECB) tf_ecb_decrypt(key, tmpdata, macvrfy, TF_FROM_BITS(macbits));
                else if (ctr_mode == TFC_MODE_CBC) tf_cbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits));
+               else if (ctr_mode == TFC_MODE_PCBC) tf_pcbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits));
 
                if (!memcmp(tmpdata, macresult, TF_FROM_BITS(macbits))) {
                        if (quiet == NO) {
@@ -1377,6 +1384,7 @@ _shortmac:        memset(macvrfy, 0, sizeof(macvrfy));
                else if (ctr_mode == TFC_MODE_XTS) tf_xts_encrypt(key, xtskey, ctr, tmpdata, macresult, TF_FROM_BITS(macbits), xtsblocks);
                else if (ctr_mode == TFC_MODE_ECB) tf_ecb_encrypt(key, tmpdata, macresult, TF_FROM_BITS(macbits));
                else if (ctr_mode == TFC_MODE_CBC) tf_cbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits));
+               else if (ctr_mode == TFC_MODE_PCBC) tf_pcbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits));
                memset(macresult, 0, sizeof(macresult));
 
                if (!do_mac_file) {
index 280661480c65787ed1a545e9bdbadc1dd25f278a..ad12ef8a941f3417ec7ae3fc6d4d1b3fc9974a34 100644 (file)
--- a/tfcrypt.h
+++ b/tfcrypt.h
@@ -234,7 +234,7 @@ enum { TFC_RAWKEY_KEYFILE = 1, TFC_RAWKEY_ASKSTR, TFC_RAWKEY_ASKHEX };
 enum { TFC_OUTFMT_HEX = 1, TFC_OUTFMT_B64, TFC_OUTFMT_RAW };
 enum {
        TFC_MODE_SKSUM = -2, TFC_MODE_PLAIN = -1, TFC_MODE_CTR = 1,
-       TFC_MODE_STREAM, TFC_MODE_XTS, TFC_MODE_ECB, TFC_MODE_CBC
+       TFC_MODE_STREAM, TFC_MODE_XTS, TFC_MODE_ECB, TFC_MODE_CBC, TFC_MODE_PCBC
 };
 enum { TFC_CTR_SHOW = 1, TFC_CTR_HEAD, TFC_CTR_RAND, TFC_CTR_ZERO, TFC_CTR_SSET };
 enum { TFC_NO_FTRUNC, TFC_DO_FTRUNC, TFC_FTRUNC_TAIL };
diff --git a/tfdef.h b/tfdef.h
index 0facb028e2999dc74a1c804ba5cd9911c08e6ab4..539ed42da8c9a9cfd646ef93233d3fe29c5e8f1e 100644 (file)
--- a/tfdef.h
+++ b/tfdef.h
@@ -147,6 +147,8 @@ void tf_ecb_encrypt(const void *key, void *out, const void *in, size_t sz);
 void tf_ecb_decrypt(const void *key, void *out, const void *in, size_t sz);
 void tf_cbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz);
 void tf_cbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz);
+void tf_pcbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz);
+void tf_pcbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz);
 void tf_xts_encrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi);
 void tf_xts_decrypt(const void *keyx, const void *keyz, void *ctr, void *out, const void *in, size_t sz, size_t bpi);
 
diff --git a/tfpcbc.c b/tfpcbc.c
new file mode 100644 (file)
index 0000000..72ac9a3
--- /dev/null
+++ b/tfpcbc.c
@@ -0,0 +1,86 @@
+#include <string.h>
+#include "tfdef.h"
+
+void tf_pcbc_encrypt(const void *key, void *iv, void *out, const void *in, size_t sz)
+{
+       const TF_BYTE_TYPE *uin = (const TF_BYTE_TYPE *)in;
+       TF_BYTE_TYPE *uout = (TF_BYTE_TYPE *)out;
+       TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+       TF_UNIT_TYPE *uiv = (TF_UNIT_TYPE *)iv;
+       const TF_UNIT_TYPE *ukey = (const TF_UNIT_TYPE *)key;
+       size_t sl = sz, i;
+
+       if (sl >= TF_BLOCK_SIZE) {
+               do {
+                       memcpy(x, uin, TF_BLOCK_SIZE);
+                       uin += TF_BLOCK_SIZE;
+                       data_to_words(x, TF_BLOCK_SIZE);
+
+                       for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] = x[i] ^ uiv[i];
+                       tf_encrypt_rawblk(y, y, ukey);
+                       for (i = 0; i < TF_NR_BLOCK_UNITS; i++) uiv[i] = y[i] ^ x[i];
+
+                       data_to_words(y, TF_BLOCK_SIZE);
+                       memcpy(uout, y, TF_BLOCK_SIZE);
+                       uout += TF_BLOCK_SIZE;
+               } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+       }
+
+       if (sl) {
+               memset(x, 0, TF_BLOCK_SIZE);
+               memcpy(x, uin, sl);
+               data_to_words(x, TF_BLOCK_SIZE);
+
+               ctr_inc(uiv, TF_NR_BLOCK_UNITS);
+               tf_encrypt_rawblk(y, uiv, ukey);
+               for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+               data_to_words(y, TF_BLOCK_SIZE);
+               memcpy(uout, y, sl);
+       }
+
+       memset(x, 0, TF_BLOCK_SIZE);
+       memset(y, 0, TF_BLOCK_SIZE);
+}
+
+void tf_pcbc_decrypt(const void *key, void *iv, void *out, const void *in, size_t sz)
+{
+       const TF_BYTE_TYPE *uin = (const TF_BYTE_TYPE *)in;
+       TF_BYTE_TYPE *uout = (TF_BYTE_TYPE *)out;
+       TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
+       TF_UNIT_TYPE *uiv = (TF_UNIT_TYPE *)iv;
+       const TF_UNIT_TYPE *ukey = (const TF_UNIT_TYPE *)key;
+       size_t sl = sz, i;
+
+       if (sl >= TF_BLOCK_SIZE) {
+               do {
+                       memcpy(x, uin, TF_BLOCK_SIZE);
+                       uin += TF_BLOCK_SIZE;
+                       data_to_words(x, TF_BLOCK_SIZE);
+
+                       tf_decrypt_rawblk(y, x, ukey);
+                       for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= uiv[i];
+                       for (i = 0; i < TF_NR_BLOCK_UNITS; i++) uiv[i] = y[i] ^ x[i];
+
+                       data_to_words(y, TF_BLOCK_SIZE);
+                       memcpy(uout, y, TF_BLOCK_SIZE);
+                       uout += TF_BLOCK_SIZE;
+               } while ((sl -= TF_BLOCK_SIZE) >= TF_BLOCK_SIZE);
+       }
+
+       if (sl) {
+               memset(x, 0, TF_BLOCK_SIZE);
+               memcpy(x, uin, sl);
+               data_to_words(x, TF_BLOCK_SIZE);
+
+               ctr_inc(uiv, TF_NR_BLOCK_UNITS);
+               tf_encrypt_rawblk(y, uiv, ukey);
+               for (i = 0; i < TF_NR_BLOCK_UNITS; i++) y[i] ^= x[i];
+
+               data_to_words(y, TF_BLOCK_SIZE);
+               memcpy(uout, y, sl);
+       }
+
+       memset(x, 0, TF_BLOCK_SIZE);
+       memset(y, 0, TF_BLOCK_SIZE);
+}