0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/module.h>
0016 #include <linux/types.h>
0017 #include <linux/crypto.h>
0018 #include <linux/err.h>
0019 #include <crypto/algapi.h>
0020 #include <crypto/b128ops.h>
0021 #include <crypto/internal/simd.h>
0022 #include <crypto/serpent.h>
0023
0024 #include "serpent-sse2.h"
0025 #include "ecb_cbc_helpers.h"
0026
0027 static int serpent_setkey_skcipher(struct crypto_skcipher *tfm,
0028 const u8 *key, unsigned int keylen)
0029 {
0030 return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen);
0031 }
0032
0033 static void serpent_decrypt_cbc_xway(const void *ctx, u8 *dst, const u8 *src)
0034 {
0035 u8 buf[SERPENT_PARALLEL_BLOCKS - 1][SERPENT_BLOCK_SIZE];
0036 const u8 *s = src;
0037
0038 if (dst == src)
0039 s = memcpy(buf, src, sizeof(buf));
0040 serpent_dec_blk_xway(ctx, dst, src);
0041 crypto_xor(dst + SERPENT_BLOCK_SIZE, s, sizeof(buf));
0042 }
0043
0044 static int ecb_encrypt(struct skcipher_request *req)
0045 {
0046 ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
0047 ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_enc_blk_xway);
0048 ECB_BLOCK(1, __serpent_encrypt);
0049 ECB_WALK_END();
0050 }
0051
0052 static int ecb_decrypt(struct skcipher_request *req)
0053 {
0054 ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
0055 ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_dec_blk_xway);
0056 ECB_BLOCK(1, __serpent_decrypt);
0057 ECB_WALK_END();
0058 }
0059
0060 static int cbc_encrypt(struct skcipher_request *req)
0061 {
0062 CBC_WALK_START(req, SERPENT_BLOCK_SIZE, -1);
0063 CBC_ENC_BLOCK(__serpent_encrypt);
0064 CBC_WALK_END();
0065 }
0066
0067 static int cbc_decrypt(struct skcipher_request *req)
0068 {
0069 CBC_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
0070 CBC_DEC_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_decrypt_cbc_xway);
0071 CBC_DEC_BLOCK(1, __serpent_decrypt);
0072 CBC_WALK_END();
0073 }
0074
0075 static struct skcipher_alg serpent_algs[] = {
0076 {
0077 .base.cra_name = "__ecb(serpent)",
0078 .base.cra_driver_name = "__ecb-serpent-sse2",
0079 .base.cra_priority = 400,
0080 .base.cra_flags = CRYPTO_ALG_INTERNAL,
0081 .base.cra_blocksize = SERPENT_BLOCK_SIZE,
0082 .base.cra_ctxsize = sizeof(struct serpent_ctx),
0083 .base.cra_module = THIS_MODULE,
0084 .min_keysize = SERPENT_MIN_KEY_SIZE,
0085 .max_keysize = SERPENT_MAX_KEY_SIZE,
0086 .setkey = serpent_setkey_skcipher,
0087 .encrypt = ecb_encrypt,
0088 .decrypt = ecb_decrypt,
0089 }, {
0090 .base.cra_name = "__cbc(serpent)",
0091 .base.cra_driver_name = "__cbc-serpent-sse2",
0092 .base.cra_priority = 400,
0093 .base.cra_flags = CRYPTO_ALG_INTERNAL,
0094 .base.cra_blocksize = SERPENT_BLOCK_SIZE,
0095 .base.cra_ctxsize = sizeof(struct serpent_ctx),
0096 .base.cra_module = THIS_MODULE,
0097 .min_keysize = SERPENT_MIN_KEY_SIZE,
0098 .max_keysize = SERPENT_MAX_KEY_SIZE,
0099 .ivsize = SERPENT_BLOCK_SIZE,
0100 .setkey = serpent_setkey_skcipher,
0101 .encrypt = cbc_encrypt,
0102 .decrypt = cbc_decrypt,
0103 },
0104 };
0105
0106 static struct simd_skcipher_alg *serpent_simd_algs[ARRAY_SIZE(serpent_algs)];
0107
0108 static int __init serpent_sse2_init(void)
0109 {
0110 if (!boot_cpu_has(X86_FEATURE_XMM2)) {
0111 printk(KERN_INFO "SSE2 instructions are not detected.\n");
0112 return -ENODEV;
0113 }
0114
0115 return simd_register_skciphers_compat(serpent_algs,
0116 ARRAY_SIZE(serpent_algs),
0117 serpent_simd_algs);
0118 }
0119
0120 static void __exit serpent_sse2_exit(void)
0121 {
0122 simd_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs),
0123 serpent_simd_algs);
0124 }
0125
0126 module_init(serpent_sse2_init);
0127 module_exit(serpent_sse2_exit);
0128
0129 MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized");
0130 MODULE_LICENSE("GPL");
0131 MODULE_ALIAS_CRYPTO("serpent");