Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Glue Code for SSE2 assembler versions of Serpent Cipher
0004  *
0005  * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
0006  *
0007  * Glue code based on aesni-intel_glue.c by:
0008  *  Copyright (C) 2008, Intel Corp.
0009  *    Author: Huang Ying <ying.huang@intel.com>
0010  *
0011  * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
0012  *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
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");