From f5397c396bfedcd6de90ab648fa600aca3b22bbb Mon Sep 17 00:00:00 2001 From: Andrey Rys Date: Sun, 28 Aug 2022 15:20:36 +0200 Subject: [PATCH] Add Propagating CBC (PCBC) mode --- VERSION | 2 +- tfc_bench.c | 4 +++ tfc_conf.c | 2 ++ tfc_misc.c | 1 + tfcrypt.c | 8 +++++ tfcrypt.h | 2 +- tfdef.h | 2 ++ tfpcbc.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 tfpcbc.c diff --git a/VERSION b/VERSION index 69a893a..3fdcd7c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -66 +67 diff --git a/tfc_bench.c b/tfc_bench.c index 2c05538..e05ac78 100644 --- a/tfc_bench.c +++ b/tfc_bench.c @@ -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; } diff --git a/tfc_conf.c b/tfc_conf.c index fc9bec7..fe36a13 100644 --- a/tfc_conf.c +++ b/tfc_conf.c @@ -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")) diff --git a/tfc_misc.c b/tfc_misc.c index 01998f2..5902896 100644 --- a/tfc_misc.c +++ b/tfc_misc.c @@ -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; diff --git a/tfcrypt.c b/tfcrypt.c index cb126ae..45438cb 100644 --- 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) { diff --git a/tfcrypt.h b/tfcrypt.h index 2806614..ad12ef8 100644 --- 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 0facb02..539ed42 100644 --- 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 index 0000000..72ac9a3 --- /dev/null +++ b/tfpcbc.c @@ -0,0 +1,86 @@ +#include +#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); +} -- 2.31.1