Re: [RFC PATCH 1/7] crypto: xctr - Add XCTR support

Ard Biesheuvel
2022-01-27T10:00:31Z

On Tue, 25 Jan 2022 at 02:46, Nathan Huckleberry <nhuck@google.com> wrote:
>
> Add a generic implementation of XCTR mode as a template. XCTR is a
> blockcipher mode similar to CTR mode. XCTR uses XORs and little-endian
> addition rather than big-endian arithmetic which makes it slightly
> faster on little-endian CPUs. It is used as a component to implement
> HCTR2.
>
> More information on XCTR mode can be found in the HCTR2 paper:
> https://eprint.iacr.org/2021/1441.pdf
>
> Signed-off-by: Nathan Huckleberry <nhuck@google.com>
> ---
> crypto/Kconfig | 9 +
> crypto/Makefile | 1 +
> crypto/tcrypt.c | 1 +
> crypto/testmgr.c | 6 +
> crypto/testmgr.h | 546 ++++++++++++++++++++++++++++++++++++++++++
> crypto/xctr.c | 202 ++++++++++++++++
> include/crypto/xctr.h | 19 ++
> 7 files changed, 784 insertions(+)
> create mode 100644 crypto/xctr.c
> create mode 100644 include/crypto/xctr.h
>
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index 94bfa32cc6a1..b00de5f22eaf 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -452,6 +452,15 @@ config CRYPTO_PCBC
> PCBC: Propagating Cipher Block Chaining mode
> This block cipher algorithm is required for RxRPC.
>
> +config CRYPTO_XCTR
> + tristate
> + select CRYPTO_SKCIPHER
> + select CRYPTO_MANAGER
> + help
> + XCTR: XOR Counter mode. This blockcipher mode is a variant of CTR mode
> + using XORs and little-endian addition rather than big-endian arithmetic.
> + XCTR mode is used to implement HCTR2.
> +
> config CRYPTO_XTS
> tristate "XTS support"
> select CRYPTO_SKCIPHER
> diff --git a/crypto/Makefile b/crypto/Makefile
> index d76bff8d0ffd..6b3fe3df1489 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -93,6 +93,7 @@ obj-$(CONFIG_CRYPTO_CTS) += cts.o
> obj-$(CONFIG_CRYPTO_LRW) += lrw.o
> obj-$(CONFIG_CRYPTO_XTS) += xts.o
> obj-$(CONFIG_CRYPTO_CTR) += ctr.o
> +obj-$(CONFIG_CRYPTO_XCTR) += xctr.o
> obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
> obj-$(CONFIG_CRYPTO_ADIANTUM) += adiantum.o
> obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o
> diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
> index 00149657a4bc..da7848f84d12 100644
> --- a/crypto/tcrypt.c
> +++ b/crypto/tcrypt.c
> @@ -1750,6 +1750,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
> ret += tcrypt_test("rfc3686(ctr(aes))");
> ret += tcrypt_test("ofb(aes)");
> ret += tcrypt_test("cfb(aes)");
> + ret += tcrypt_test("xctr(aes)");
> break;
>
> case 11:
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 5831d4bbc64f..5acf92354543 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -5454,6 +5454,12 @@ static const struct alg_test_desc alg_test_descs[] = {
> .suite = {
> .cipher = __VECS(xchacha20_tv_template)
> },
> + }, {
> + .alg = "xctr(aes)",
> + .test = alg_test_skcipher,
> + .suite = {
> + .cipher = __VECS(aes_xctr_tv_template)
> + }
> }, {
> .alg = "xts(aes)",
> .generic_driver = "xts(ecb(aes-generic))",
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index a253d66ba1c1..e1ebbb3c4d4c 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -32800,4 +32800,550 @@ static const struct hash_testvec blakes2s_256_tv_template[] = {{
> 0xd5, 0x06, 0xb5, 0x3a, 0x7c, 0x7a, 0x65, 0x1d, },
> }};
>
> +/*
> + * Test vectors generated using https://github.com/google/hctr2
> + */
> +static const struct cipher_testvec aes_xctr_tv_template[] = {
> + {
> + .key = "\x06\x20\x5d\xba\x50\xb5\x12\x8e"
> + "\xee\x65\x3c\x59\x80\xa1\xfe\xb1",
> + .iv = "\x16\x52\x22\x0d\x1c\x76\x94\x9f"
> + "\x74\xba\x41\x0c\xc4\xc4\xaf\xb9",
> + .ptext = "\x02\x62\x54\x87\x28\x8f\xa1\xd3"
> + "\x8f\xd8\xc6\xab\x08\xef\xea\x83"
> + "\xa3\xbd\xf4\x85\x47\x66\x74\x11"
> + "\xf1\x58\x9f\x9f\xe8\xb9\x95\xc9",
> + .ctext = "\x11\xfe\xef\xb4\x9e\xed\x5b\xe5"
> + "\x92\x9b\x03\xa7\x6d\x8e\xf9\x7a"
> + "\xaa\xfa\x33\x4a\xf7\xd9\xb2\xeb"
> + "\x73\xa1\x85\xbc\x45\xbc\x42\x70",
> + .klen = 16,
> + .len = 32,
> + },
> + {
> + .key = "\x19\x0e\xea\x30\x59\x8e\x39\x35"
> + "\x93\x63\xcc\x8b\x5f\x98\x4f\x43",
> + .iv = "\x4b\x9f\xf4\xd8\xaa\xcf\x99\xdc"
> + "\xc5\x07\xe0\xde\xb2\x6d\x85\x12",
> + .ptext = "\x23\x2d\x48\x15\x89\x34\x54\xf9"
> + "\x2b\x38\xd1\x62\x06\x98\x21\x59"
> + "\xd4\x3a\x45\x6f\x12\x27\x08\xa9"
> + "\x3e\x0f\x21\x3d\xda\x80\x92\x3f",
> + .ctext = "\x01\xa7\xe5\x9e\xf8\x49\xbb\x36"
> + "\x49\xb8\x59\x7a\x77\x3f\x5a\x10"
> + "\x2e\x8f\xe7\xc9\xc4\xb8\xdb\x86"
> + "\xe4\xc0\x6b\x60\x2f\x79\xa0\x91",
> + .klen = 16,
> + .len = 32,
> + },
> + {
> + .key = "\x17\xa6\x01\x3d\x5d\xd6\xef\x2d"
> + "\x69\x8f\x4c\x54\x5b\xae\x43\xf0",
> + .iv = "\xa9\x1b\x47\x60\x26\x82\xf7\x1c"
> + "\x80\xf8\x88\xdd\xfb\x44\xd9\xda",
> + .ptext = "\xf7\x67\xcd\xa6\x04\x65\x53\x99"
> + "\x90\x5c\xa2\x56\x74\xd7\x9d\xf2"
> + "\x0b\x03\x7f\x4e\xa7\x84\x72\x2b"
> + "\xf0\xa5\xbf\xe6\x9a\x62\x3a\xfe"
> + "\x69\x5c\x93\x79\x23\x86\x64\x85"
> + "\xeb\x13\xb1\x5a\xd5\x48\x39\xa0"
> + "\x70\xfb\x06\x9a\xd7\x12\x5a\xb9"
> + "\xbe\xed\x2c\x81\x64\xf7\xcf\x80"
> + "\xee\xe6\x28\x32\x2d\x37\x4c\x32"
> + "\xf4\x1f\x23\x21\xe9\xc8\xc9\xbf"
> + "\x54\xbc\xcf\xb4\xc2\x65\x39\xdf"
> + "\xa5\xfb\x14\x11\xed\x62\x38\xcf"
> + "\x9b\x58\x11\xdd\xe9\xbd\x37\x57"
> + "\x75\x4c\x9e\xd5\x67\x0a\x48\xc6"
> + "\x0d\x05\x4e\xb1\x06\xd7\xec\x2e"
> + "\x9e\x59\xde\x4f\xab\x38\xbb\xe5"
> + "\x87\x04\x5a\x2c\x2a\xa2\x8f\x3c"
> + "\xe7\xe1\x46\xa9\x49\x9f\x24\xad"
> + "\x2d\xb0\x55\x40\x64\xd5\xda\x7e"
> + "\x1e\x77\xb8\x29\x72\x73\xc3\x84"
> + "\xcd\xf3\x94\x90\x58\x76\xc9\x2c"
> + "\x2a\xad\x56\xde\x33\x18\xb6\x3b"
> + "\x10\xe9\xe9\x8d\xf0\xa9\x7f\x05"
> + "\xf7\xb5\x8c\x13\x7e\x11\x3d\x1e"
> + "\x02\xbb\x5b\xea\x69\xff\x85\xcf"
> + "\x6a\x18\x97\x45\xe3\x96\xba\x4d"
> + "\x2d\x7a\x70\x78\x15\x2c\xe9\xdc"
> + "\x4e\x09\x92\x57\x04\xd8\x0b\xa6"
> + "\x20\x71\x76\x47\x76\x96\x89\xa0"
> + "\xd9\x29\xa2\x5a\x06\xdb\x56\x39"
> + "\x60\x33\x59\x04\x95\x89\xf6\x18"
> + "\x1d\x70\x75\x85\x3a\xb7\x6e",
> + .ctext = "\xe1\xe7\x3f\xd3\x6a\xb9\x2f\x64"
> + "\x37\xc5\xa4\xe9\xca\x0a\xa1\xd6"
> + "\xea\x7d\x39\xe5\xe6\xcc\x80\x54"
> + "\x74\x31\x2a\x04\x33\x79\x8c\x8e"
> + "\x4d\x47\x84\x28\x27\x9b\x3c\x58"
> + "\x54\x58\x20\x4f\x70\x01\x52\x5b"
> + "\xac\x95\x61\x49\x5f\xef\xba\xce"
> + "\xd7\x74\x56\xe7\xbb\xe0\x3c\xd0"
> + "\x7f\xa9\x23\x57\x33\x2a\xf6\xcb"
> + "\xbe\x42\x14\x95\xa8\xf9\x7a\x7e"
> + "\x12\x53\x3a\xe2\x13\xfe\x2d\x89"
> + "\xeb\xac\xd7\xa8\xa5\xf8\x27\xf3"
> + "\x74\x9a\x65\x63\xd1\x98\x3a\x7e"
> + "\x27\x7b\xc0\x20\x00\x4d\xf4\xe5"
> + "\x7b\x69\xa6\xa8\x06\x50\x85\xb6"
> + "\x7f\xac\x7f\xda\x1f\xf5\x37\x56"
> + "\x9b\x2f\xd3\x86\x6b\x70\xbd\x0e"
> + "\x55\x9a\x9d\x4b\x08\xb5\x5b\x7b"
> + "\xd4\x7c\xb4\x71\x49\x92\x4a\x1e"
> + "\xed\x6d\x11\x09\x47\x72\x32\x6a"
> + "\x97\x53\x36\xaf\xf3\x06\x06\x2c"
> + "\x69\xf1\x59\x00\x36\x95\x28\x2a"
> + "\xb6\xcd\x10\x21\x84\x73\x5c\x96"
> + "\x86\x14\x2c\x3d\x02\xdb\x53\x9a"
> + "\x61\xde\xea\x99\x84\x7a\x27\xf6"
> + "\xf7\xc8\x49\x73\x4b\xb8\xeb\xd3"
> + "\x41\x33\xdd\x09\x68\xe2\x64\xb8"
> + "\x5f\x75\x74\x97\x91\x54\xda\xc2"
> + "\x73\x2c\x1e\x5a\x84\x48\x01\x1a"
> + "\x0d\x8b\x0a\xdf\x07\x2e\xee\x77"
> + "\x1d\x17\x41\x7a\xc9\x33\x63\xfa"
> + "\x9f\xc3\x74\x57\x5f\x03\x4c",
> + .klen = 16,
> + .len = 255,
> + },
> + {
> + .key = "\xd1\x87\xd3\xa1\x97\x6a\x4b\xf9"
> + "\x5d\xcb\x6c\x07\x6e\x2d\x48\xad",
> + .iv = "\xe9\x8c\x88\x40\xa9\x52\xe0\xbc"
> + "\x8a\x47\x3a\x09\x5d\x60\xdd\xb2",
> + .ptext = "\x67\x80\x86\x46\x18\xc6\xed\xd2"
> + "\x99\x0f\x7a\xc3\xa5\x0b\x80\xcb"
> + "\x8d\xe4\x0b\x4c\x1e\x4c\x98\x46"
> + "\x87\x8a\x8c\x76\x75\xce\x2c\x27"
> + "\x74\x88\xdc\x37\xaa\x77\x53\x14"
> + "\xd3\x01\xcf\xb5\xcb\xdd\xb4\x8e"
> + "\x6b\x54\x68\x01\xc3\xdf\xbc\xdd"
> + "\x1a\x08\x4c\x11\xab\x25\x4b\x69"
> + "\x25\x21\x78\xb1\x91\x1b\x75\xfa"
> + "\xd0\x10\xf3\x8a\x65\xd3\x8d\x2e"
> + "\xf8\xb6\xce\x29\xf9\x1e\x45\x5f"
> + "\x4e\x41\x63\x6f\xf9\xca\x59\xd7"
> + "\xc8\x9c\x97\xda\xff\xab\x42\x47"
> + "\xfb\x2b\xca\xed\xda\x6c\x96\xe4"
> + "\x59\x0d\xc6\x4a\x26\xde\xa8\x50"
> + "\xc5\xbb\x13\xf8\xd1\xb9\x6b\xf4"
> + "\x19\x30\xfb\xc0\x4f\x6b\x96\xc4"
> + "\x88\x0b\x57\xb3\x43\xbd\xdd\xe2"
> + "\x06\xae\x88\x44\x41\xdf\xa4\x29"
> + "\x31\xd3\x38\xeb\xe9\xf8\xa2\xe4"
> + "\x6a\x55\x2f\x56\x58\x19\xeb\xf7"
> + "\x5f\x4b\x15\x52\xe4\xaa\xdc\x31"
> + "\x4a\x32\xc9\x31\x96\x68\x3b\x80"
> + "\x20\x4f\xe5\x8f\x87\xc9\x37\x58"
> + "\x79\xfd\xc9\xc1\x9a\x83\xe3\x8b"
> + "\x6b\x57\x07\xef\x28\x8d\x55\xcb"
> + "\x4e\xb6\xa2\xb6\xd3\x4f\x8b\x10"
> + "\x70\x10\x02\xf6\x74\x71\x20\x5a"
> + "\xe2\x2f\xb6\x46\xc5\x22\xa3\x29"
> + "\xf5\xc1\x25\xb0\x4d\xda\xaf\x04"
> + "\xca\x83\xe6\x3f\x66\x6e\x3b\xa4"
> + "\x09\x40\x22\xd7\x97\x12\x1e",
> + .ctext = "\xd4\x6d\xfa\xc8\x6e\x54\x31\x69"
> + "\x47\x51\x0f\xb8\xfa\x03\xa2\xe1"
> + "\x57\xa8\x4f\x2d\xc5\x4e\x8d\xcd"
> + "\x92\x0f\x71\x08\xdd\xa4\x5b\xc7"
> + "\x69\x3a\x3d\x93\x29\x1d\x87\x2c"
> + "\xfa\x96\xd2\x4d\x72\x61\xb0\x9e"
> + "\xa7\xf5\xd5\x09\x3d\x43\x32\x82"
> + "\xd2\x9a\x58\xe3\x4c\x84\xc2\xad"
> + "\x33\x77\x9c\x5d\x37\xc1\x4f\x95"
> + "\x56\x55\xc6\x76\x62\x27\x6a\xc7"
> + "\x45\x80\x9e\x7c\x48\xc8\x14\xbb"
> + "\x32\xbf\x4a\xbb\x8d\xb4\x2c\x7c"
> + "\x01\xfa\xc8\xde\x10\x55\xa0\xae"
> + "\x29\xed\xe2\x3d\xd6\x26\xfa\x3c"
> + "\x7a\x81\xae\xfd\xc3\x2f\xe5\x3a"
> + "\x00\xa3\xf0\x66\x0f\x3a\xd2\xa3"
> + "\xaf\x0e\x75\xbb\x79\xad\xcc\xe0"
> + "\x98\x10\xfb\xf1\xc0\x0c\xb9\x03"
> + "\x07\xee\x46\x6a\xc0\xf6\x17\x8f"
> + "\x7f\xc9\xad\x16\x58\x54\xb0\xd5"
> + "\x67\x73\x9f\xce\xea\x4b\x60\x57"
> + "\x1d\x62\x72\xec\xab\xe3\xd8\x32"
> + "\x29\x48\x37\x1b\x5c\xd6\xd0\xb7"
> + "\xc3\x39\xef\xf6\x1b\x18\xf6\xd1"
> + "\x2d\x76\x7c\x68\x50\x37\xfa\x8f"
> + "\x16\x87\x5e\xf8\xb1\x79\x82\x52"
> + "\xc7\x3e\x0e\xa3\x61\xb9\x00\xe0"
> + "\x2e\x03\x80\x6e\xc0\xbf\x63\x78"
> + "\xdf\xab\xc2\x3b\xf0\x4c\xb0\xcb"
> + "\x91\x6a\x26\xe6\x3a\x86\xef\x1a"
> + "\x4e\x4d\x23\x2d\x59\x3a\x02\x3a"
> + "\xf3\xda\xd1\x9d\x68\xf6\xef",
> + .klen = 16,
> + .len = 255,
> + },
> + {
> + .key = "\x17\xe6\xb1\x85\x40\x24\xbe\x80"
> + "\x99\xc7\xa1\x0c\x0f\x72\x31\xb8"
> + "\x10\xb5\x11\x21\x3a\x99\x9e\xc8",
> + .iv = "\x6b\x5f\xe1\x6a\xe1\x21\xfc\x62"
> + "\xd9\x85\x2e\x0b\xbd\x58\x79\xd1",
> + .ptext = "\xea\x3c\xad\x9d\x92\x05\x50\xa4"
> + "\x68\x56\x6b\x33\x95\xa8\x24\x6c"
> + "\xa0\x9d\x91\x15\x3a\x26\xb7\xeb"
> + "\xb4\x5d\xf7\x0c\xec\x91\xbe\x11",
> + .ctext = "\x6a\xac\xfc\x24\x64\x98\x28\x33"
> + "\xa4\x39\xfd\x72\x46\x56\x7e\xf7"
> + "\xd0\x7f\xee\x95\xd8\x68\x44\x67"
> + "\x70\x80\xd4\x69\x7a\xf5\x8d\xad",
> + .klen = 24,
> + .len = 32,
> + },
> + {
> + .key = "\x02\x81\x0e\xb1\x97\xe0\x20\x0c"
> + "\x46\x8c\x7b\xde\xac\xe6\xe0\xb5"
> + "\x2e\xb3\xc0\x40\x0e\xb7\x3d\xd3",
> + .iv = "\x37\x15\x1c\x61\xab\x95\x8f\xf3"
> + "\x11\x3a\x79\xe2\xf7\x33\x96\xb3",
> + .ptext = "\x05\xd9\x7a\xc7\x08\x79\xba\xd8"
> + "\x4a\x63\x54\xf7\x4e\x0c\x98\x8a"
> + "\x5d\x40\x05\xe4\x7a\x7a\x14\x0c"
> + "\xa8\xa7\x53\xf4\x3e\x66\x81\x38",
> + .ctext = "\x43\x66\x70\x51\xd9\x7c\x6f\x80"
> + "\x82\x8e\x34\xda\x5d\x3c\x47\xd1"
> + "\xe0\x67\x76\xb5\x78\x98\x47\x26"
> + "\x41\x31\xfa\x97\xc9\x79\xeb\x15",
> + .klen = 24,
> + .len = 32,
> + },
> + {
> + .key = "\x9a\xef\x58\x01\x4c\x1e\xa2\x33"
> + "\xce\x1f\x32\xae\xc8\x69\x1f\xf5"
> + "\x82\x1b\x74\xf4\x8b\x1b\xce\x30",
> + .iv = "\xb1\x72\x52\xa8\xc4\x8f\xb5\xec"
> + "\x95\x12\x14\x5f\xd2\x29\x14\x0f",
> + .ptext = "\x8a\xbc\x20\xbd\x67\x76\x8d\xd8"
> + "\xa6\x70\xf0\x74\x8c\x8d\x9c\x00"
> + "\xdd\xaf\xef\x28\x5d\x8d\xfa\x87"
> + "\x81\x39\x8c\xb1\x6e\x0a\xcf\x3c"
> + "\xe8\x3b\xc0\xff\x6e\xe7\xd1\xc6"
> + "\x70\xb8\xdf\x27\x62\x72\x8e\xb7"
> + "\x6b\xa7\xb2\x74\xdd\xc6\xb4\xc9"
> + "\x4c\xd8\x4f\x2c\x09\x75\x6e\xb7"
> + "\x41\xb3\x8f\x96\x09\x0d\x40\x8e"
> + "\x0f\x49\xc2\xad\xc4\xf7\x71\x0a"
> + "\x76\xfb\x45\x97\x29\x7a\xaa\x98"
> + "\x22\x55\x4f\x9c\x26\x01\xc8\xb9"
> + "\x41\x42\x51\x9d\x00\x5c\x7f\x02"
> + "\x9b\x00\xaa\xbd\x69\x47\x9c\x26"
> + "\x5b\xcb\x08\xf3\x46\x33\xf9\xeb"
> + "\x79\xdd\xfe\x38\x08\x84\x8c\x81"
> + "\xb8\x51\xbd\xcd\x72\x00\xdb\xbd"
> + "\xf5\xd6\xb4\x80\xf7\xd3\x49\xac"
> + "\x9e\xf9\xea\xd5\xad\xd4\xaa\x8f"
> + "\x97\x60\xce\x60\xa7\xdd\xc0\xb2"
> + "\x51\x80\x9b\xae\xab\x0d\x62\xab"
> + "\x78\x1a\xeb\x8c\x03\x6f\x30\xbf"
> + "\xe0\xe1\x20\x65\x74\x65\x54\x43"
> + "\x92\x57\xd2\x73\x8a\xeb\x99\x38"
> + "\xca\x78\xc8\x11\xd7\x92\x1a\x05"
> + "\x55\xb8\xfa\xa0\x82\xb7\xd6\x16"
> + "\x84\x4d\x25\xc4\xd5\xe4\x55\xf3"
> + "\x6c\xb3\xe4\x6e\x66\x31\x5c\x41"
> + "\x98\x46\x28\xd8\x71\x05\xf2\x3b"
> + "\xd1\x3e\x0f\x79\x7f\xf3\x30\x3f"
> + "\xbe\x36\xf4\x50\xbd\x0c\x89\xd5"
> + "\xcb\x53\x9f\xeb\x56\xf4\x3f",
> + .ctext = "\xee\x90\xe1\x45\xf5\xab\x04\x23"
> + "\x70\x0a\x54\x49\xac\x34\xb8\x69"
> + "\x3f\xa8\xce\xef\x6e\x63\xc1\x20"
> + "\x7a\x41\x43\x5d\xa2\x29\x71\x1d"
> + "\xd2\xbb\xb1\xca\xb4\x3a\x5a\xf3"
> + "\x0a\x68\x0b\x9d\x6f\x68\x60\x9e"
> + "\x9d\xb9\x23\x68\xbb\xdd\x12\x31"
> + "\xc6\xd6\xf9\xb3\x80\xe8\xb5\xab"
> + "\x84\x2a\x8e\x7b\xb2\x4f\xee\x31"
> + "\x83\xc4\x1c\x80\x89\xe4\xe7\xd2"
> + "\x00\x65\x98\xd1\x57\xcc\xf6\x87"
> + "\x14\xf1\x23\x22\x78\x61\xc7\xb6"
> + "\xf5\x90\x97\xdd\xcd\x90\x98\xd8"
> + "\xbb\x02\xfa\x2c\xf0\x89\xfc\x7e"
> + "\xe7\xcd\xee\x41\x3f\x73\x4a\x08"
> + "\xf8\x8f\xf3\xbf\x3a\xd5\xce\xb7"
> + "\x7a\xf4\x49\xcd\x3f\xc7\x1f\x77"
> + "\x98\xd0\x9d\x82\x20\x8a\x04\x5d"
> + "\x9f\x77\xcb\xf4\x38\x92\x47\xce"
> + "\x6d\xc3\x51\xc1\xd9\xf4\x2f\x65"
> + "\x67\x01\xf4\x46\x3b\xd2\x90\x5d"
> + "\x2a\xcb\xc5\x39\x1c\x72\xa5\xba"
> + "\xaf\x80\x9b\x87\x01\x85\xa1\x02"
> + "\xdf\x79\x4c\x27\x77\x3e\xfc\xb3"
> + "\x96\xbc\x42\xad\xdf\xa4\x16\x1e"
> + "\x77\xe7\x39\xcc\x78\x2c\xc1\x00"
> + "\xe5\xa6\xb5\x9b\x0c\x12\x19\xc5"
> + "\x8b\xbe\xae\x4b\xc3\xa3\x91\x8f"
> + "\x5b\x82\x0f\x20\x30\x35\x45\x26"
> + "\x29\x84\x2e\xc8\x2d\xce\xae\xac"
> + "\xbe\x93\x50\x7a\x6a\x01\x08\x38"
> + "\xf5\x49\x4d\x8b\x7e\x96\x70",
> + .klen = 24,
> + .len = 255,
> + },
> + {
> + .key = "\x2c\x3c\x6c\x78\xaa\x83\xed\x14"
> + "\x4e\xe5\xe2\x3e\x1e\x89\xcb\x2f"
> + "\x19\x5a\x70\x50\x09\x81\x43\x75",
> + .iv = "\xa5\x57\x8e\x3c\xba\x52\x87\x4f"
> + "\xb7\x45\x26\xab\x31\xb9\x58\xfa",
> + .ptext = "\x43\x29\x69\x02\xf0\xc0\x64\xf3"
> + "\xe1\x85\x75\x25\x11\x5d\x18\xf8"
> + "\xdc\x96\x82\x1b\xee\x4d\x01\xd2"
> + "\x28\x83\xbb\xfe\xe1\x72\x14\x3c"
> + "\xe9\xe5\x9f\x8c\x40\xb5\x0a\xaa"
> + "\x9f\xb8\xc5\xf1\x01\x05\x65\x79"
> + "\x90\x05\xeb\xac\xa8\x52\x35\xc4"
> + "\x2d\x56\x0d\xe1\x37\x09\xb8\xec"
> + "\x51\xd8\x79\x13\x5b\x85\x8c\x14"
> + "\x77\xe3\x64\xea\x89\xb1\x04\x9d"
> + "\x6c\x58\x1b\x51\x54\x1f\xc7\x2f"
> + "\xc8\x3d\xa6\x93\x39\xce\x77\x3a"
> + "\x93\xc2\xaa\x88\xcc\x09\xfa\xc4"
> + "\x5e\x92\x3b\x46\xd2\xd6\xd4\x5d"
> + "\x31\x58\xc5\xc6\x30\xb8\x7f\x77"
> + "\x0f\x1b\xf8\x9a\x7d\x3f\x56\x90"
> + "\x61\x8f\x08\x8f\x61\x64\x8e\xf4"
> + "\xaa\x7c\xf8\x4c\x0b\xab\x47\x2a"
> + "\x0d\xa7\x24\x36\x59\xfe\x94\xfc"
> + "\x38\x38\x32\xdf\x73\x1b\x75\xb1"
> + "\x6f\xa2\xd8\x0b\xa1\xd4\x31\x58"
> + "\xaa\x24\x11\x22\xc9\xf7\x83\x3c"
> + "\x6e\xee\x75\xc0\xdd\x3b\x21\x99"
> + "\x9f\xde\x81\x9c\x2a\x70\xc4\xb8"
> + "\xc6\x27\x4e\x5d\x9a\x4a\xe1\x75"
> + "\x01\x95\x47\x87\x3f\x9a\x69\x20"
> + "\xb4\x66\x70\x1a\xe2\xb3\x6c\xfa"
> + "\x1f\x6e\xf9\xc3\x8a\x1f\x0b\x0b"
> + "\xc5\x92\xba\xd9\xf8\x27\x6b\x97"
> + "\x01\xe2\x38\x01\x7f\x06\xde\x54"
> + "\xb7\x78\xbc\x7d\x6a\xa1\xf2\x6f"
> + "\x62\x42\x30\xbf\xb1\x6d\xc7",
> + .ctext = "\x53\xc0\xb3\x13\x8f\xbf\x88\x1a"
> + "\x6f\xda\xad\x0b\x33\x8b\x82\x9d"
> + "\xca\x17\x32\x65\xaa\x72\x24\x1b"
> + "\x95\x33\xcc\x5b\x58\x5d\x08\x58"
> + "\xe5\x52\xc0\xb7\xc6\x97\x77\x66"
> + "\xbd\xf4\x50\xde\xe1\xf0\x70\x61"
> + "\xc2\x05\xce\xe0\x90\x2f\x7f\xb3"
> + "\x04\x7a\xee\xbe\xb3\xb7\xaf\xda"
> + "\x3c\xb8\x95\xb4\x20\xba\x66\x0b"
> + "\x97\xcc\x07\x3f\x22\x07\x0e\xea"
> + "\x76\xd8\x32\xf9\x34\x47\xcb\xaa"
> + "\xb3\x5a\x06\x68\xac\x94\x10\x39"
> + "\xf2\x70\xe1\x7b\x98\x5c\x0c\xcb"
> + "\x8f\xd8\x48\xfa\x2e\x15\xa1\xf1"
> + "\x2f\x85\x55\x39\xd8\x24\xe6\xc1"
> + "\x6f\xd7\x52\x97\x42\x7a\x2e\x14"
> + "\x39\x74\x16\xf3\x8b\xbd\x38\xb9"
> + "\x54\x20\xc6\x31\x1b\x4c\xb7\x26"
> + "\xd4\x71\x63\x97\xaa\xbf\xf5\xb7"
> + "\x17\x5e\xee\x14\x67\x38\x14\x11"
> + "\xf6\x98\x3c\x70\x4a\x89\xf4\x27"
> + "\xb4\x72\x7a\xc0\x5d\x58\x3d\x8b"
> + "\xf6\xf7\x80\x7b\xa9\xa7\x4d\xf8"
> + "\x1a\xbe\x07\x0c\x06\x97\x25\xc8"
> + "\x5a\x18\xae\x21\xa6\xe4\x77\x13"
> + "\x5a\xe5\xf5\xe0\xd5\x48\x73\x22"
> + "\x68\xde\x70\x05\xc4\xdf\xd5\x7c"
> + "\xa0\x2b\x99\x9c\xa8\x21\xd7\x6c"
> + "\x55\x97\x09\xd6\xb0\x62\x93\x90"
> + "\x14\xb1\xd1\x83\x5a\xb3\x17\xb9"
> + "\xc7\xcc\x6b\x51\x23\x44\x4b\xef"
> + "\x48\x0f\x0f\xf0\x0e\xa1\x8f",
> + .klen = 24,
> + .len = 255,
> + },
> + {
> + .key = "\xed\xd1\xcf\x81\x1c\xf8\x9d\x56"
> + "\xd4\x3b\x86\x4b\x65\x96\xfe\xe8"
> + "\x8a\xd4\x3b\xd7\x76\x07\xab\xf4"
> + "\xe9\xae\xd1\x4d\x50\x9b\x94\x1c",
> + .iv = "\x09\x90\xf3\x7c\x15\x99\x7d\x94"
> + "\x88\xf4\x99\x19\xd1\x62\xc4\x65",
> + .ptext = "\xa2\x06\x41\x55\x60\x2c\xe3\x76"
> + "\xa9\xaf\xf9\xe1\xd7\x0d\x65\x49"
> + "\xda\x27\x0d\xf8\xec\xdc\x09\x2b"
> + "\x06\x24\xe4\xd5\x15\x29\x6b\x5f",
> + .ctext = "\xad\x5c\xd0\xc1\x03\x45\xba\x9d"
> + "\xab\x6d\x82\xae\xf7\x8e\x2b\x8b"
> + "\xd8\x61\xe6\x96\x5c\x5c\xe2\x70"
> + "\xe5\x19\x0a\x04\x60\xca\x45\xfc",
> + .klen = 32,
> + .len = 32,
> + },
> + {
> + .key = "\xf8\x75\xa6\xba\x7b\x00\xf0\x71"
> + "\x24\x5d\xdf\x93\x8b\xa3\x7d\x6d"
> + "\x8e\x0f\x65\xf4\xe2\xbe\x2b\xaa"
> + "\x2a\x0d\x9e\x00\x6a\x94\x80\xa1",
> + .iv = "\xb9\xb7\x55\x26\x5f\x96\x16\x68"
> + "\x5c\x5f\x58\xbb\x4e\x5a\xe1\x3b",
> + .ptext = "\x2f\xd9\x2c\xc2\x98\x1e\x81\x5e"
> + "\x89\xc8\xec\x1f\x56\x3e\xd9\xa4"
> + "\x92\x48\xec\xfc\x5d\xeb\x7f\xad"
> + "\x7a\x47\xe6\xda\x71\x1b\x2e\xfa",
> + .ctext = "\x25\x5e\x38\x20\xcf\xbe\x4c\x6c"
> + "\xe6\xce\xfc\xe2\xca\x6a\xa1\x62"
> + "\x3a\xb7\xdf\x21\x3e\x49\xa6\xb8"
> + "\x22\xd2\xc8\x37\xa4\x55\x09\xe6",
> + .klen = 32,
> + .len = 32,
> + },
> + {
> + .key = "\x32\x37\x2b\x8f\x7b\xb1\x23\x79"
> + "\x05\x52\xde\x05\xf1\x68\x3f\x6c"
> + "\xa4\xae\xbc\x21\xc2\xc6\xf0\xbd"
> + "\x0f\x20\xb7\xa4\xc5\x05\x7b\x64",
> + .iv = "\xff\x26\x4e\x67\x48\xdd\xcf\xfe"
> + "\x42\x09\x04\x98\x5f\x1e\xfa\x80",
> + .ptext = "\x99\xdc\x3b\x19\x41\xf9\xff\x6e"
> + "\x76\xb5\x03\xfa\x61\xed\xf8\x44"
> + "\x70\xb9\xf0\x83\x80\x6e\x31\x77"
> + "\x77\xe4\xc7\xb4\x77\x02\xab\x91"
> + "\x82\xc6\xf8\x7c\x46\x61\x03\x69"
> + "\x09\xa0\xf7\x12\xb7\x81\x6c\xa9"
> + "\x10\x5c\xbb\x55\xb3\x44\xed\xb5"
> + "\xa2\x52\x48\x71\x90\x5d\xda\x40"
> + "\x0b\x7f\x4a\x11\x6d\xa7\x3d\x8e"
> + "\x1b\xcd\x9d\x4e\x75\x8b\x7d\x87"
> + "\xe5\x39\x34\x32\x1e\xe6\x8d\x51"
> + "\xd4\x1f\xe3\x1d\x50\xa0\x22\x37"
> + "\x7c\xb0\xd9\xfb\xb6\xb2\x16\xf6"
> + "\x6d\x26\xa0\x4e\x8c\x6a\xe6\xb6"
> + "\xbe\x4c\x7c\xe3\x88\x10\x18\x90"
> + "\x11\x50\x19\x90\xe7\x19\x3f\xd0"
> + "\x31\x15\x0f\x06\x96\xfe\xa7\x7b"
> + "\xc3\x32\x88\x69\xa4\x12\xe3\x64"
> + "\x02\x30\x17\x74\x6c\x88\x7c\x9b"
> + "\xd6\x6d\x75\xdf\x11\x86\x70\x79"
> + "\x48\x7d\x34\x3e\x33\x58\x07\x8b"
> + "\xd2\x50\xac\x35\x15\x45\x05\xb4"
> + "\x4d\x31\x97\x19\x87\x23\x4b\x87"
> + "\x53\xdc\xa9\x19\x78\xf1\xbf\x35"
> + "\x30\x04\x14\xd4\xcf\xb2\x8c\x87"
> + "\x7d\xdb\x69\xc9\xcd\xfe\x40\x3e"
> + "\x8d\x66\x5b\x61\xe5\xf0\x2d\x87"
> + "\x93\x3a\x0c\x2b\x04\x98\x05\xc2"
> + "\x56\x4d\xc4\x6c\xcd\x7a\x98\x7e"
> + "\xe2\x2d\x79\x07\x91\x9f\xdf\x2f"
> + "\x72\xc9\x8f\xcb\x0b\x87\x1b\xb7"
> + "\x04\x86\xcb\x47\xfa\x5d\x03",
> + .ctext = "\x0b\x00\xf7\xf2\xc8\x6a\xba\x9a"
> + "\x0a\x97\x18\x7a\x00\xa0\xdb\xf4"
> + "\x5e\x8e\x4a\xb7\xe0\x51\xf1\x75"
> + "\x17\x8b\xb4\xf1\x56\x11\x05\x9f"
> + "\x2f\x2e\xba\x67\x04\xe1\xb4\xa5"
> + "\xfc\x7c\x8c\xad\xc6\xb9\xd1\x64"
> + "\xca\xbd\x5d\xaf\xdb\x65\x48\x4f"
> + "\x1b\xb3\x94\x5c\x0b\xd0\xee\xcd"
> + "\xb5\x7f\x43\x8a\xd8\x8b\x66\xde"
> + "\xd2\x9c\x13\x65\xa4\x47\xa7\x03"
> + "\xc5\xa1\x46\x8f\x2f\x84\xbc\xef"
> + "\x48\x9d\x9d\xb5\xbd\x43\xff\xd2"
> + "\xd2\x7a\x5a\x13\xbf\xb4\xf6\x05"
> + "\x17\xcd\x01\x12\xf0\x35\x27\x96"
> + "\xf4\xc1\x65\xf7\x69\xef\x64\x1b"
> + "\x6e\x4a\xe8\x77\xce\x83\x01\xb7"
> + "\x60\xe6\x45\x2a\xcd\x41\x4a\xb5"
> + "\x8e\xcc\x45\x93\xf1\xd6\x64\x5f"
> + "\x32\x60\xe4\x29\x4a\x82\x6c\x86"
> + "\x16\xe4\xcc\xdb\x5f\xc8\x11\xa6"
> + "\xfe\x88\xd6\xc3\xe5\x5c\xbb\x67"
> + "\xec\xa5\x7b\xf5\xa8\x4f\x77\x25"
> + "\x5d\x0c\x2a\x99\xf9\xb9\xd1\xae"
> + "\x3c\x83\x2a\x93\x9b\x66\xec\x68"
> + "\x2c\x93\x02\x8a\x8a\x1e\x2f\x50"
> + "\x09\x37\x19\x5c\x2a\x3a\xc2\xcb"
> + "\xcb\x89\x82\x81\xb7\xbb\xef\x73"
> + "\x8b\xc9\xae\x42\x96\xef\x70\xc0"
> + "\x89\xc7\x3e\x6a\x26\xc3\xe4\x39"
> + "\x53\xa9\xcf\x63\x7d\x05\xf3\xff"
> + "\x52\x04\xf6\x7f\x23\x96\xe9\xf7"
> + "\xff\xd6\x50\xa3\x0e\x20\x71",
> + .klen = 32,
> + .len = 255,
> + },
> + {
> + .key = "\x49\x85\x84\x69\xd4\x5f\xf9\xdb"
> + "\xf2\xc4\x1c\x62\x20\x88\xea\x8a"
> + "\x5b\x69\xe6\x3b\xe2\x5c\xfe\xce"
> + "\xe1\x7a\x27\x7b\x1c\xc9\xb4\x43",
> + .iv = "\xae\x98\xdb\xef\x5c\x6b\xe9\x27"
> + "\x1a\x2f\x51\x17\x97\x7d\x4f\x10",
> + .ptext = "\xbe\xf2\x8f\x8a\x51\x9e\x3d\xff"
> + "\xd7\x68\x0f\xd2\xf2\x5b\xe3\xa5"
> + "\x59\x3e\xcd\xab\x46\xc6\xe9\x24"
> + "\x43\xbc\xb8\x37\x1f\x55\x7f\xb5"
> + "\xc0\xa6\x68\xdf\xbf\x21\x1e\xed"
> + "\x67\x73\xb7\x06\x47\xff\x67\x07"
> + "\x5b\x94\xab\xef\x43\x95\x52\xce"
> + "\xe7\x71\xbd\x72\x5b\x3a\x25\x01"
> + "\xed\x7d\x02\x2d\x72\xd6\xc4\x3d"
> + "\xd2\xf5\xe5\xb3\xf2\xd7\xa1\x8d"
> + "\x12\x0d\x3b\x4a\x58\xf4\x1b\xfd"
> + "\xcd\x2c\x13\x05\x07\x3d\x30\x8a"
> + "\x1f\xc6\xed\xfc\x7c\x3c\xa6\x1c"
> + "\x64\x2c\x36\xa8\x5d\xe2\xfa\x12"
> + "\xd7\x17\xa9\x39\x43\x63\xbf\x44"
> + "\xd0\xcb\x4c\xf0\xab\xe6\x75\xd6"
> + "\x60\xd1\x64\x9e\x01\x2b\x97\x52"
> + "\x97\x24\x32\xb0\xfa\x22\xf4\x04"
> + "\xe6\x98\x6a\xbc\xba\xe8\x65\xad"
> + "\x60\x08\xfc\xd7\x40\xf8\x2a\xf2"
> + "\x5e\x32\x32\x82\x24\x12\xda\xbc"
> + "\x8f\x1c\xd4\x06\x81\x08\x80\x35"
> + "\x20\xa5\xa8\x3a\x6e\x3e\x2f\x78"
> + "\xe4\x7d\x9e\x81\x43\xb8\xfe\xa7"
> + "\x3b\xa9\x9b\x1a\xe7\xce\xd2\x3d"
> + "\xc1\x27\x26\x22\x35\x12\xa2\xc6"
> + "\x59\x51\x22\x31\x7b\xc8\xca\xa6"
> + "\xa9\xf3\x16\x57\x72\x3d\xfa\x24"
> + "\x66\x56\x5d\x21\x29\x9e\xf2\xff"
> + "\xae\x0c\x71\xcf\xc5\xf0\x98\xe5"
> + "\xa1\x05\x96\x94\x3e\x36\xed\x97"
> + "\xc7\xee\xcd\xc2\x54\x35\x5c",
> + .ctext = "\xde\x7f\x5e\xac\x6f\xec\xed\x2a"
> + "\x3a\x3b\xb3\x36\x19\x46\x26\x27"
> + "\x09\x7b\x49\x47\x1b\x88\x43\xb7"
> + "\x65\x67\xef\x0b\xe4\xde\x0a\x97"
> + "\x7f\xab\x32\x7c\xa2\xde\x4e\xba"
> + "\x11\x9b\x19\x12\x7d\x03\x01\x15"
> + "\xa3\x90\x9f\x52\x9d\x29\x3d\x5c"
> + "\xc6\x71\x59\x2c\x44\x8f\xb7\x8c"
> + "\x0d\x75\x81\x76\xe2\x11\x96\x41"
> + "\xae\x48\x27\x0e\xbc\xaf\x1d\xf5"
> + "\x51\x68\x5a\x34\xe5\x6d\xdf\x60"
> + "\xc7\x9d\x4e\x1a\xaa\xb5\x1a\x57"
> + "\x58\x6a\xa4\x79\x0a\xa9\x50\x8d"
> + "\x93\x59\xef\x5b\x23\xdb\xc8\xb3"
> + "\x38\x96\x8c\xdf\x7d\x6a\x3d\x53"
> + "\x84\x9d\xb0\xf0\x07\x5f\xff\x67"
> + "\xff\x5b\x3c\x8b\x1f\xa2\x3b\xcf"
> + "\xf5\x86\x7c\xbc\x98\x38\x7a\xe5"
> + "\x96\x56\xba\x44\x85\x29\x4f\x3a"
> + "\x64\xde\xec\xc6\x53\xf0\x30\xca"
> + "\xa4\x90\x4f\x9c\x2e\x0e\xec\x2d"
> + "\x8c\x38\x1c\x93\x9a\x5d\x5d\x98"
> + "\xf9\x2c\xf7\x27\x71\x3c\x69\xa9"
> + "\x0b\xec\xd9\x9c\x6c\x69\x09\x47"
> + "\xd9\xc2\x84\x6e\x3e\x2d\x9f\x1f"
> + "\xb6\x13\x62\x4c\xf3\x33\x44\x13"
> + "\x6c\x43\x0a\xae\x8e\x89\xd6\x27"
> + "\xdd\xc3\x5b\x37\x62\x09\x47\x94"
> + "\xe3\xea\x7d\x08\x14\x70\xb1\x8e"
> + "\x83\x4a\xcb\xc0\xa9\xf2\xa3\x02"
> + "\xe9\xa0\x44\xfe\xcf\x5a\x15\x50"
> + "\xc4\x5a\x6f\xc8\xd6\xf1\x83",
> + .klen = 32,
> + .len = 255,
> + },
> +};
> +
> #endif /* _CRYPTO_TESTMGR_H */
> diff --git a/crypto/xctr.c b/crypto/xctr.c
> new file mode 100644
> index 000000000000..dfb44c092cc4
> --- /dev/null
> +++ b/crypto/xctr.c
> @@ -0,0 +1,202 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * XCTR: XOR Counter mode - Adapted from ctr.c
> + *
> + * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
> + * Copyright 2021 Google LLC
> + */
> +
> +/*
> + * XCTR mode is a blockcipher mode of operation used to implement HCTR2. XCTR is
> + * closely related to the CTR mode of operation; the main difference is that CTR
> + * generates the keystream using E(CTR + IV) whereas XCTR generates the
> + * keystream using E(CTR ^ IV).
> + *
> + * See the HCTR2 paper for more details:
> + * Length-preserving encryption with HCTR2
> + * (https://eprint.iacr.org/2021/1441.pdf)
> + */
> +
> +#include <crypto/algapi.h>
> +#include <crypto/xctr.h>
> +#include <crypto/internal/cipher.h>
> +#include <crypto/internal/skcipher.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +static void crypto_xctr_crypt_final(struct skcipher_walk *walk,
> + struct crypto_cipher *tfm, u32 byte_ctr)
> +{
> + unsigned int bsize = crypto_cipher_blocksize(tfm);
> + unsigned long alignmask = crypto_cipher_alignmask(tfm);
> + u8 ctr[MAX_CIPHER_BLOCKSIZE];
> + u8 ctrblk[MAX_CIPHER_BLOCKSIZE];
> + u8 tmp[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK];
> + u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
> + u8 *src = walk->src.virt.addr;
> + u8 *dst = walk->dst.virt.addr;
> + unsigned int nbytes = walk->nbytes;
> + u32 ctr32 = byte_ctr / bsize + 1;
> +
> + u32_to_le_block(ctr, ctr32, bsize);
> + crypto_xor_cpy(ctrblk, ctr, walk->iv, bsize);
> + crypto_cipher_encrypt_one(tfm, keystream, ctrblk);
> + crypto_xor_cpy(dst, keystream, src, nbytes);
> +}
> +
> +static int crypto_xctr_crypt_segment(struct skcipher_walk *walk,
> + struct crypto_cipher *tfm, u32 byte_ctr)
> +{
> + void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
> + crypto_cipher_alg(tfm)->cia_encrypt;
> + unsigned int bsize = crypto_cipher_blocksize(tfm);
> + u8 ctr[MAX_CIPHER_BLOCKSIZE];
> + u8 ctrblk[MAX_CIPHER_BLOCKSIZE];
> + u8 *src = walk->src.virt.addr;
> + u8 *dst = walk->dst.virt.addr;
> + unsigned int nbytes = walk->nbytes;
> + u32 ctr32 = byte_ctr / bsize + 1;
> +
> + do {
> + /* create keystream */
> + u32_to_le_block(ctr, ctr32, bsize);
> + crypto_xor_cpy(ctrblk, ctr, walk->iv, bsize);
> + fn(crypto_cipher_tfm(tfm), dst, ctrblk);
> + crypto_xor(dst, src, bsize);
> +
> + ctr32++;
> +
> + src += bsize;
> + dst += bsize;
> + } while ((nbytes -= bsize) >= bsize);
> +
> + return nbytes;
> +}
> +
> +static int crypto_xctr_crypt_inplace(struct skcipher_walk *walk,
> + struct crypto_cipher *tfm, u32 byte_ctr)
> +{
> + void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
> + crypto_cipher_alg(tfm)->cia_encrypt;
> + unsigned int bsize = crypto_cipher_blocksize(tfm);
> + unsigned long alignmask = crypto_cipher_alignmask(tfm);
> + unsigned int nbytes = walk->nbytes;
> + u8 ctr[MAX_CIPHER_BLOCKSIZE];
> + u8 ctrblk[MAX_CIPHER_BLOCKSIZE];
> + u8 *src = walk->src.virt.addr;
> + u8 tmp[MAX_CIPHER_BLOCKSIZE + MAX_CIPHER_ALIGNMASK];
> + u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
> + u32 ctr32 = byte_ctr / bsize + 1;
> +
> + u32_to_le_block(ctr, ctr32, bsize);
> + do {
> + /* create keystream */
> + u32_to_le_block(ctr, ctr32, bsize);
> + crypto_xor_cpy(ctrblk, ctr, walk->iv, bsize);
> + fn(crypto_cipher_tfm(tfm), keystream, ctrblk);
> + crypto_xor(src, keystream, bsize);
> +
> + ctr32++;
> +
> + src += bsize;
> + } while ((nbytes -= bsize) >= bsize);
> +
> + return nbytes;
> +}
> +
> +static int crypto_xctr_crypt(struct skcipher_request *req)
> +{
> + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
> + struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
> + const unsigned int bsize = crypto_cipher_blocksize(cipher);
> + struct skcipher_walk walk;
> + unsigned int nbytes;
> + int err;
> + u32 byte_ctr = 0;
> +
> + err = skcipher_walk_virt(&walk, req, false);
> +
> + while (walk.nbytes >= bsize) {
> + if (walk.src.virt.addr == walk.dst.virt.addr)
> + nbytes = crypto_xctr_crypt_inplace(&walk, cipher, byte_ctr);
> + else
> + nbytes = crypto_xctr_crypt_segment(&walk, cipher, byte_ctr);
> +
> + byte_ctr += walk.nbytes - nbytes;
> + err = skcipher_walk_done(&walk, nbytes);
> + }
> +
> + if (walk.nbytes) {
> + crypto_xctr_crypt_final(&walk, cipher, byte_ctr);
> + err = skcipher_walk_done(&walk, 0);
> + }
> +
> + return err;
> +}
> +
> +static int crypto_xctr_create(struct crypto_template *tmpl, struct rtattr **tb)
> +{
> + struct skcipher_instance *inst;
> + struct crypto_alg *alg;
> + int err;
> +
> + inst = skcipher_alloc_instance_simple(tmpl, tb);
> + if (IS_ERR(inst))
> + return PTR_ERR(inst);
> +
> + alg = skcipher_ialg_simple(inst);
> +
> + /* Block size must be >= 4 bytes. */
> + err = -EINVAL;
> + if (alg->cra_blocksize < 4)
> + goto out_free_inst;
> +
> + /* XCTR mode is a stream cipher. */
> + inst->alg.base.cra_blocksize = 1;
> +
> + /*
> + * To simplify the implementation, configure the skcipher walk to only
> + * give a partial block at the very end, never earlier.
> + */
> + inst->alg.chunksize = alg->cra_blocksize;
> +
> + inst->alg.encrypt = crypto_xctr_crypt;
> + inst->alg.decrypt = crypto_xctr_crypt;
> +
> + err = skcipher_register_instance(tmpl, inst);
> + if (err) {
> +out_free_inst:
> + inst->free(inst);
> + }
> +
> + return err;
> +}
> +
> +static struct crypto_template crypto_xctr_tmpl[] = {
> + {
> + .name = "xctr",
> + .create = crypto_xctr_create,
> + .module = THIS_MODULE,
> + }
> +};
> +
> +static int __init crypto_xctr_module_init(void)
> +{
> + return crypto_register_template(crypto_xctr_tmpl);
> +}
> +
> +static void __exit crypto_xctr_module_exit(void)
> +{
> + crypto_unregister_template(crypto_xctr_tmpl);
> +}
> +
> +subsys_initcall(crypto_xctr_module_init);
> +module_exit(crypto_xctr_module_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("XCTR block cipher mode of operation");
> +MODULE_ALIAS_CRYPTO("xctr");
> +MODULE_IMPORT_NS(CRYPTO_INTERNAL);
> diff --git a/include/crypto/xctr.h b/include/crypto/xctr.h
> new file mode 100644
> index 000000000000..0d025e08ca26
> --- /dev/null
> +++ b/include/crypto/xctr.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * XCTR: XOR Counter mode
> + *
> + * Copyright 2021 Google LLC
> + */
> +
> +#include <asm/unaligned.h>
> +
> +#ifndef _CRYPTO_XCTR_H
> +#define _CRYPTO_XCTR_H
> +
> +static inline void u32_to_le_block(u8 *a, u32 x, unsigned int size)
> +{
> + memset(a, 0, size);
> + put_unaligned(cpu_to_le32(x), (u32 *)a);

Please use put_unaligned_le32() here.

And casting 'a' to (u32 *) is invalid C, so just pass 'a' directly.
Otherwise, the compiler might infer that 'a' is guaranteed to be
aligned after all, and use an aligned access instead.

> +}
> +
> +#endif /* _CRYPTO_XCTR_H */
> --
> 2.35.0.rc0.227.g00780c9af4-goog
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel