1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Glue Code for SSE2 assembler versions of Serpent Cipher
5 * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
7 * Glue code based on aesni-intel_glue.c by:
8 * Copyright (C) 2008, Intel Corp.
9 * Author: Huang Ying <ying.huang@intel.com>
11 * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
12 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
13 * CTR part based on code (crypto/ctr.c) by:
14 * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/crypto.h>
20 #include <linux/err.h>
21 #include <crypto/algapi.h>
22 #include <crypto/b128ops.h>
23 #include <crypto/internal/simd.h>
24 #include <crypto/serpent.h>
25 #include <asm/crypto/serpent-sse2.h>
26 #include <asm/crypto/glue_helper.h>
28 static int serpent_setkey_skcipher(struct crypto_skcipher
*tfm
,
29 const u8
*key
, unsigned int keylen
)
31 return __serpent_setkey(crypto_skcipher_ctx(tfm
), key
, keylen
);
34 static void serpent_decrypt_cbc_xway(const void *ctx
, u8
*d
, const u8
*s
)
36 u128 ivs
[SERPENT_PARALLEL_BLOCKS
- 1];
37 u128
*dst
= (u128
*)d
;
38 const u128
*src
= (const u128
*)s
;
41 for (j
= 0; j
< SERPENT_PARALLEL_BLOCKS
- 1; j
++)
44 serpent_dec_blk_xway(ctx
, (u8
*)dst
, (u8
*)src
);
46 for (j
= 0; j
< SERPENT_PARALLEL_BLOCKS
- 1; j
++)
47 u128_xor(dst
+ (j
+ 1), dst
+ (j
+ 1), ivs
+ j
);
50 static void serpent_crypt_ctr(const void *ctx
, u8
*d
, const u8
*s
, le128
*iv
)
53 u128
*dst
= (u128
*)d
;
54 const u128
*src
= (const u128
*)s
;
56 le128_to_be128(&ctrblk
, iv
);
59 __serpent_encrypt(ctx
, (u8
*)&ctrblk
, (u8
*)&ctrblk
);
60 u128_xor(dst
, src
, (u128
*)&ctrblk
);
63 static void serpent_crypt_ctr_xway(const void *ctx
, u8
*d
, const u8
*s
,
66 be128 ctrblks
[SERPENT_PARALLEL_BLOCKS
];
67 u128
*dst
= (u128
*)d
;
68 const u128
*src
= (const u128
*)s
;
71 for (i
= 0; i
< SERPENT_PARALLEL_BLOCKS
; i
++) {
75 le128_to_be128(&ctrblks
[i
], iv
);
79 serpent_enc_blk_xway_xor(ctx
, (u8
*)dst
, (u8
*)ctrblks
);
82 static const struct common_glue_ctx serpent_enc
= {
84 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
87 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
88 .fn_u
= { .ecb
= serpent_enc_blk_xway
}
91 .fn_u
= { .ecb
= __serpent_encrypt
}
95 static const struct common_glue_ctx serpent_ctr
= {
97 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
100 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
101 .fn_u
= { .ctr
= serpent_crypt_ctr_xway
}
104 .fn_u
= { .ctr
= serpent_crypt_ctr
}
108 static const struct common_glue_ctx serpent_dec
= {
110 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
113 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
114 .fn_u
= { .ecb
= serpent_dec_blk_xway
}
117 .fn_u
= { .ecb
= __serpent_decrypt
}
121 static const struct common_glue_ctx serpent_dec_cbc
= {
123 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
126 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
127 .fn_u
= { .cbc
= serpent_decrypt_cbc_xway
}
130 .fn_u
= { .cbc
= __serpent_decrypt
}
134 static int ecb_encrypt(struct skcipher_request
*req
)
136 return glue_ecb_req_128bit(&serpent_enc
, req
);
139 static int ecb_decrypt(struct skcipher_request
*req
)
141 return glue_ecb_req_128bit(&serpent_dec
, req
);
144 static int cbc_encrypt(struct skcipher_request
*req
)
146 return glue_cbc_encrypt_req_128bit(__serpent_encrypt
,
150 static int cbc_decrypt(struct skcipher_request
*req
)
152 return glue_cbc_decrypt_req_128bit(&serpent_dec_cbc
, req
);
155 static int ctr_crypt(struct skcipher_request
*req
)
157 return glue_ctr_req_128bit(&serpent_ctr
, req
);
160 static struct skcipher_alg serpent_algs
[] = {
162 .base
.cra_name
= "__ecb(serpent)",
163 .base
.cra_driver_name
= "__ecb-serpent-sse2",
164 .base
.cra_priority
= 400,
165 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
166 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
167 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
168 .base
.cra_module
= THIS_MODULE
,
169 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
170 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
171 .setkey
= serpent_setkey_skcipher
,
172 .encrypt
= ecb_encrypt
,
173 .decrypt
= ecb_decrypt
,
175 .base
.cra_name
= "__cbc(serpent)",
176 .base
.cra_driver_name
= "__cbc-serpent-sse2",
177 .base
.cra_priority
= 400,
178 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
179 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
180 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
181 .base
.cra_module
= THIS_MODULE
,
182 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
183 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
184 .ivsize
= SERPENT_BLOCK_SIZE
,
185 .setkey
= serpent_setkey_skcipher
,
186 .encrypt
= cbc_encrypt
,
187 .decrypt
= cbc_decrypt
,
189 .base
.cra_name
= "__ctr(serpent)",
190 .base
.cra_driver_name
= "__ctr-serpent-sse2",
191 .base
.cra_priority
= 400,
192 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
193 .base
.cra_blocksize
= 1,
194 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
195 .base
.cra_module
= THIS_MODULE
,
196 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
197 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
198 .ivsize
= SERPENT_BLOCK_SIZE
,
199 .chunksize
= SERPENT_BLOCK_SIZE
,
200 .setkey
= serpent_setkey_skcipher
,
201 .encrypt
= ctr_crypt
,
202 .decrypt
= ctr_crypt
,
206 static struct simd_skcipher_alg
*serpent_simd_algs
[ARRAY_SIZE(serpent_algs
)];
208 static int __init
serpent_sse2_init(void)
210 if (!boot_cpu_has(X86_FEATURE_XMM2
)) {
211 printk(KERN_INFO
"SSE2 instructions are not detected.\n");
215 return simd_register_skciphers_compat(serpent_algs
,
216 ARRAY_SIZE(serpent_algs
),
220 static void __exit
serpent_sse2_exit(void)
222 simd_unregister_skciphers(serpent_algs
, ARRAY_SIZE(serpent_algs
),
226 module_init(serpent_sse2_init
);
227 module_exit(serpent_sse2_exit
);
229 MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized");
230 MODULE_LICENSE("GPL");
231 MODULE_ALIAS_CRYPTO("serpent");