11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2937c30d7SJussi Kivilinna /* 3937c30d7SJussi Kivilinna * Glue Code for SSE2 assembler versions of Serpent Cipher 4937c30d7SJussi Kivilinna * 5937c30d7SJussi Kivilinna * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 6937c30d7SJussi Kivilinna * 7937c30d7SJussi Kivilinna * Glue code based on aesni-intel_glue.c by: 8937c30d7SJussi Kivilinna * Copyright (C) 2008, Intel Corp. 9937c30d7SJussi Kivilinna * Author: Huang Ying <ying.huang@intel.com> 10937c30d7SJussi Kivilinna * 11937c30d7SJussi Kivilinna * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: 12937c30d7SJussi Kivilinna * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 13937c30d7SJussi Kivilinna */ 14937c30d7SJussi Kivilinna 15937c30d7SJussi Kivilinna #include <linux/module.h> 16937c30d7SJussi Kivilinna #include <linux/types.h> 17937c30d7SJussi Kivilinna #include <linux/crypto.h> 18937c30d7SJussi Kivilinna #include <linux/err.h> 19937c30d7SJussi Kivilinna #include <crypto/algapi.h> 20937c30d7SJussi Kivilinna #include <crypto/b128ops.h> 21e0f409dcSEric Biggers #include <crypto/internal/simd.h> 22e0f409dcSEric Biggers #include <crypto/serpent.h> 23d4af0e9dSJussi Kivilinna #include <asm/crypto/serpent-sse2.h> 24*9ad58b46SArd Biesheuvel 25*9ad58b46SArd Biesheuvel #include "ecb_cbc_helpers.h" 26937c30d7SJussi Kivilinna 27e0f409dcSEric Biggers static int serpent_setkey_skcipher(struct crypto_skcipher *tfm, 28e0f409dcSEric Biggers const u8 *key, unsigned int keylen) 29e0f409dcSEric Biggers { 30e0f409dcSEric Biggers return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen); 31e0f409dcSEric Biggers } 32e0f409dcSEric Biggers 33*9ad58b46SArd Biesheuvel static void serpent_decrypt_cbc_xway(const void *ctx, u8 *dst, const u8 *src) 34e81792fbSJussi Kivilinna { 35*9ad58b46SArd Biesheuvel u8 buf[SERPENT_PARALLEL_BLOCKS - 1][SERPENT_BLOCK_SIZE]; 36*9ad58b46SArd Biesheuvel const u8 *s = src; 37e81792fbSJussi Kivilinna 38*9ad58b46SArd Biesheuvel if (dst == src) 39*9ad58b46SArd Biesheuvel s = memcpy(buf, src, sizeof(buf)); 40*9ad58b46SArd Biesheuvel serpent_dec_blk_xway(ctx, dst, src); 41*9ad58b46SArd Biesheuvel crypto_xor(dst + SERPENT_BLOCK_SIZE, s, sizeof(buf)); 42e81792fbSJussi Kivilinna } 43e81792fbSJussi Kivilinna 44e0f409dcSEric Biggers static int ecb_encrypt(struct skcipher_request *req) 45e81792fbSJussi Kivilinna { 46*9ad58b46SArd Biesheuvel ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS); 47*9ad58b46SArd Biesheuvel ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_enc_blk_xway); 48*9ad58b46SArd Biesheuvel ECB_BLOCK(1, __serpent_encrypt); 49*9ad58b46SArd Biesheuvel ECB_WALK_END(); 50e81792fbSJussi Kivilinna } 51e81792fbSJussi Kivilinna 52e0f409dcSEric Biggers static int ecb_decrypt(struct skcipher_request *req) 53e81792fbSJussi Kivilinna { 54*9ad58b46SArd Biesheuvel ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS); 55*9ad58b46SArd Biesheuvel ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_dec_blk_xway); 56*9ad58b46SArd Biesheuvel ECB_BLOCK(1, __serpent_decrypt); 57*9ad58b46SArd Biesheuvel ECB_WALK_END(); 58e81792fbSJussi Kivilinna } 59e81792fbSJussi Kivilinna 60e0f409dcSEric Biggers static int cbc_encrypt(struct skcipher_request *req) 61e81792fbSJussi Kivilinna { 62*9ad58b46SArd Biesheuvel CBC_WALK_START(req, SERPENT_BLOCK_SIZE, -1); 63*9ad58b46SArd Biesheuvel CBC_ENC_BLOCK(__serpent_encrypt); 64*9ad58b46SArd Biesheuvel CBC_WALK_END(); 65e81792fbSJussi Kivilinna } 66e81792fbSJussi Kivilinna 67e0f409dcSEric Biggers static int cbc_decrypt(struct skcipher_request *req) 68e81792fbSJussi Kivilinna { 69*9ad58b46SArd Biesheuvel CBC_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS); 70*9ad58b46SArd Biesheuvel CBC_DEC_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_decrypt_cbc_xway); 71*9ad58b46SArd Biesheuvel CBC_DEC_BLOCK(1, __serpent_decrypt); 72*9ad58b46SArd Biesheuvel CBC_WALK_END(); 73e81792fbSJussi Kivilinna } 74e81792fbSJussi Kivilinna 75e0f409dcSEric Biggers static struct skcipher_alg serpent_algs[] = { 76e0f409dcSEric Biggers { 77e0f409dcSEric Biggers .base.cra_name = "__ecb(serpent)", 78e0f409dcSEric Biggers .base.cra_driver_name = "__ecb-serpent-sse2", 79e0f409dcSEric Biggers .base.cra_priority = 400, 80e0f409dcSEric Biggers .base.cra_flags = CRYPTO_ALG_INTERNAL, 81e0f409dcSEric Biggers .base.cra_blocksize = SERPENT_BLOCK_SIZE, 82e0f409dcSEric Biggers .base.cra_ctxsize = sizeof(struct serpent_ctx), 83e0f409dcSEric Biggers .base.cra_module = THIS_MODULE, 8435474c3bSJussi Kivilinna .min_keysize = SERPENT_MIN_KEY_SIZE, 8535474c3bSJussi Kivilinna .max_keysize = SERPENT_MAX_KEY_SIZE, 86e0f409dcSEric Biggers .setkey = serpent_setkey_skcipher, 8735474c3bSJussi Kivilinna .encrypt = ecb_encrypt, 8835474c3bSJussi Kivilinna .decrypt = ecb_decrypt, 8935474c3bSJussi Kivilinna }, { 90e0f409dcSEric Biggers .base.cra_name = "__cbc(serpent)", 91e0f409dcSEric Biggers .base.cra_driver_name = "__cbc-serpent-sse2", 92e0f409dcSEric Biggers .base.cra_priority = 400, 93e0f409dcSEric Biggers .base.cra_flags = CRYPTO_ALG_INTERNAL, 94e0f409dcSEric Biggers .base.cra_blocksize = SERPENT_BLOCK_SIZE, 95e0f409dcSEric Biggers .base.cra_ctxsize = sizeof(struct serpent_ctx), 96e0f409dcSEric Biggers .base.cra_module = THIS_MODULE, 9735474c3bSJussi Kivilinna .min_keysize = SERPENT_MIN_KEY_SIZE, 9835474c3bSJussi Kivilinna .max_keysize = SERPENT_MAX_KEY_SIZE, 9935474c3bSJussi Kivilinna .ivsize = SERPENT_BLOCK_SIZE, 100e0f409dcSEric Biggers .setkey = serpent_setkey_skcipher, 101e0f409dcSEric Biggers .encrypt = cbc_encrypt, 102e0f409dcSEric Biggers .decrypt = cbc_decrypt, 10335474c3bSJussi Kivilinna }, 104e0f409dcSEric Biggers }; 105e0f409dcSEric Biggers 106e0f409dcSEric Biggers static struct simd_skcipher_alg *serpent_simd_algs[ARRAY_SIZE(serpent_algs)]; 1075962f8b6SJussi Kivilinna 108937c30d7SJussi Kivilinna static int __init serpent_sse2_init(void) 109937c30d7SJussi Kivilinna { 110054efb64SBorislav Petkov if (!boot_cpu_has(X86_FEATURE_XMM2)) { 111937c30d7SJussi Kivilinna printk(KERN_INFO "SSE2 instructions are not detected.\n"); 112937c30d7SJussi Kivilinna return -ENODEV; 113937c30d7SJussi Kivilinna } 114937c30d7SJussi Kivilinna 115e0f409dcSEric Biggers return simd_register_skciphers_compat(serpent_algs, 116e0f409dcSEric Biggers ARRAY_SIZE(serpent_algs), 117e0f409dcSEric Biggers serpent_simd_algs); 118937c30d7SJussi Kivilinna } 119937c30d7SJussi Kivilinna 120937c30d7SJussi Kivilinna static void __exit serpent_sse2_exit(void) 121937c30d7SJussi Kivilinna { 122e0f409dcSEric Biggers simd_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs), 123e0f409dcSEric Biggers serpent_simd_algs); 124937c30d7SJussi Kivilinna } 125937c30d7SJussi Kivilinna 126937c30d7SJussi Kivilinna module_init(serpent_sse2_init); 127937c30d7SJussi Kivilinna module_exit(serpent_sse2_exit); 128937c30d7SJussi Kivilinna 129937c30d7SJussi Kivilinna MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized"); 130937c30d7SJussi Kivilinna MODULE_LICENSE("GPL"); 1315d26a105SKees Cook MODULE_ALIAS_CRYPTO("serpent"); 132